事件绑定发生在挂载阶段的最后一步,即VNode打补丁生成真实DOM后,通过addEventListener动态添加监听器,而非存在于虚拟DOM中。

Vue 渲染流程中,事件处理的绑定不是在模板解析时“立即执行”,而是在真实 DOM 节点挂载完成之后,通过原生 addEventListener 动态添加的。整个过程紧密耦合于 Vue 的响应式更新与虚拟 DOM 生命周期。
事件绑定发生在渲染的哪个阶段?
事件绑定属于挂载(mount)阶段的最后一步,具体顺序是:
- 模板编译为渲染函数
- 渲染函数执行,生成虚拟节点(VNode)
- VNode 对比并打补丁(patch),创建或更新真实 DOM 元素
- 对带有
v-on或@的元素,调用addEventListener绑定对应事件监听器
也就是说,事件监听器不会出现在虚拟 DOM 结构里,而是直接附加到真实 DOM 上——这是性能优化的关键:避免每次 diff 都重新绑定事件。
@click="handler" 底层做了什么?
当你写 @click="handleClick",Vue 实际做了三件事:
立即学习“前端免费学习笔记(深入)”;
递归分析 Vue 项目组件依赖,从入口文件生成组件层级图,支持 Vue 2/3,输出组件名、文件路径和属性。适用于分析组件结构、排查依赖或了解项目架构。
- 将表达式
handleClick封装为一个闭包函数,确保能访问当前组件实例(this)和响应式数据 - 在挂载时,对目标 DOM 元素调用
el.addEventListener('click', wrapper) - 这个
wrapper函数会自动注入原生事件对象e;若你在模板中显式写了$event,它就会作为实参传入方法
例如:@click="submit('save', $event) → 触发时等价于 submit('save', e)。
事件修饰符(.stop、.prevent)怎么生效?
修饰符不是语法糖的“装饰”,而是在 wrapper 函数内部提前调用对应方法:
-
@click.prevent→ wrapper 内部第一行执行e.preventDefault() -
@click.stop→ wrapper 内部第一行执行e.stopPropagation() - 多个修饰符按书写顺序依次执行,如
.stop.prevent先阻止冒泡再阻止默认行为
它们不改变事件监听本身,只影响事件触发后的处理逻辑,且完全基于原生 Event API,无额外运行时开销。
为什么 methods 中的 this 指向组件实例?
Vue 在初始化时,会对 methods 对象中的每个函数做 bind(vm) 处理(Options API)或使用箭头函数/Proxy 代理(Composition API),确保无论事件如何触发,this 始终指向当前组件实例。这也意味着你可以在 handler 中安全读写 this.count、调用 this.$emit 或访问 computed 属性。

















