Vue 事件系统

在模板里写一行 @click="handler",背后却是一套从编译器到渲染器、再到 DOM 事件再绑定的精密流水线。本文带你拆解事件在 Vue 内部的完整生命周期。

一、事件的「身份」:props 的一种

模板:

vue 复制代码
<p @click="clickHandler">text</p>

经过编译器后,事件被翻译成虚拟节点里的一个普通属性:

js 复制代码
const vnode = {
  type: 'p',
  props: {
    onClick: clickHandler   // 注意首字母大写
  },
  children: 'text'
}

因此,在渲染器眼里,事件与 idclass 没有本质区别,只是 key 以 on 开头。

二、首次挂载

渲染器在 patchProps 阶段发现 props key 以 on 开头,就进入事件分支:

js 复制代码
if (/^on/.test(key)) {
  const eventName = key.slice(2).toLowerCase() // onClick -> click
  el.addEventListener(eventName, nextValue)
}

此时事件处理器被直接绑定到 DOM 节点,首屏即生效。

三、更新策略

如果每次更新都「先 remove 再 add」,会带来无谓的性能损耗。Vue 采用 invoker 代理 解决这一问题:

  1. 在元素上新建一个隐藏属性 el._vei(Vue Event Invoker),它是一个对象。
  2. 对象的键是事件名,值是一个固定引用的代理函数 invoker
  3. invoker 内部持有真正的事件数组或函数,更新时只需替换引用,无需重新绑定。

核心逻辑:

js 复制代码
const invokers = el._vei || (el._vei = {})
let invoker = invokers[eventName]

if (!invoker) {
  invoker = invokers[eventName] = (e) => {
    const fns = invoker.value
    Array.isArray(fns) ? fns.forEach(fn => fn(e)) : fns(e)
  }
  el.addEventListener(eventName, invoker)
}
invoker.value = nextValue   // 指向最新处理器

nextValue 是空数组或 null 时,直接 removeEventListener 即可卸载。

四、多处理器与同类型多事件

模板支持数组语法:

vue 复制代码
<button @click="[fn1, fn2]" @contextmenu="fn3" />

invoker 内部检测到 Array.isArray(value),就循环执行所有函数,实现「同类型多处理器」零成本扩展。

总结

Vue 的事件系统用一句话概括:

事件即 props,props 即数据,数据变化即更新,更新即最小化 DOM 操作。

理解 invoker 代理模式,你就拥有了在源码层面定位事件问题、优化事件性能的全部钥匙。

相关推荐
AC赳赳老秦5 分钟前
OpenClaw image-processing技能实操:批量抠图、图片尺寸调整,适配办公需求
开发语言·前端·人工智能·python·深度学习·机器学习·openclaw
sbjdhjd7 分钟前
Docker | 核心概念科普 + 保姆级部署
linux·运维·服务器·docker·云原生·面试·eureka
We་ct13 分钟前
LeetCode 172. 阶乘后的零:从暴力到最优,拆解解题核心
开发语言·前端·javascript·算法·leetcode·typescript
军军君0113 分钟前
数字孪生监控大屏实战模板:可视化数字统计展示
前端·javascript·vue.js·typescript·echarts·数字孪生·前端大屏
此刻觐神20 分钟前
IMX6ULL开发板学习-03(Linux文件相关命令)
前端·chrome
吴声子夜歌37 分钟前
ES6——Iterator和for...of循环详解
前端·javascript·es6
小李子呢021141 分钟前
前端八股3---ref和reactive
开发语言·前端·javascript
落魄江湖行1 小时前
基础篇三 Nuxt4 组件进阶:插槽与事件传递
前端·nuxt4
kerli1 小时前
Compose 组件:LazyColumn 核心参数与 key/contentType 详解
android·前端
好运的阿财1 小时前
“锟斤拷”问题——程序中用powershell执行命令出现中文乱码的解决办法
linux·前端·人工智能·机器学习·架构·编辑器·vim