全部学科
NodeJS全栈
nodejs
Python全栈
python
小程序首页
📅 2026-05-20 8 分钟 ✍️ juanwangdev

事件系统底层实现

Vue事件系统核心是自定义事件总线,基于发布订阅模式实现组件间通信。

事件API实现

$on 事件监听

JavaScript
// 简化版实现
Vue.prototype.$on = function(event, fn) {
  const vm = this
  vm._events[event] = vm._events[event] || []
  vm._events[event].push(fn)
  return vm
}

事件存储在 _events 对象中,支持同一事件注册多个回调。

$emit 事件触发

JavaScript
Vue.prototype.$emit = function(event) {
  const vm = this
  let cbs = vm._events[event]
  if (cbs) {
    const args = toArray(arguments, 1)
    cbs = cbs.slice()
    for (let i = 0, l = cbs.length; i < l; i++) {
      cbs[i].apply(vm, args)
    }
  }
  return vm
}

使用 slice() 创建副本避免运行时回调数组被修改导致的问题。

$off 事件移除

JavaScript
Vue.prototype.$off = function(event, fn) {
  const vm = this
  if (!arguments.length) {
    vm._events = Object.create(null)
    return vm
  }
  if (!fn) {
    vm._events[event] = null
    return vm
  }
  let cbs = vm._events[event]
  let i = cbs.length
  while (i--) {
    if (cbs[i] === fn) {
      cbs.splice(i, 1)
      break
    }
  }
  return vm
}

支持三种移除方式:移除所有、移除某事件所有、移除特定回调。

组件事件绑定流程

JavaScript
// 模板: <Child @custom="handler"/>
// 编译后
createElement(Child, {
  on: { custom: handler }
})

父组件通过 on 选项传递事件回调,子组件通过 $emit 触发。

事件修饰符底层处理

JavaScript
// v-on:click.stop="handler"
function withModifiers(fn, modifiers) {
  if (modifiers.includes('stop')) {
    return function(e) {
      e.stopPropagation()
      return fn(e)
    }
  }
  if (modifiers.includes('prevent')) {
    return function(e) {
      e.preventDefault()
      return fn(e)
    }
  }
}

修饰符本质是事件对象的方法调用包装。

$once 一次性事件

JavaScript
Vue.prototype.$once = function(event, fn) {
  const vm = this
  function on() {
    vm.$off(event, on)
    fn.apply(vm, arguments)
  }
  on.fn = fn
  vm.$on(event, on)
  return vm
}

内部创建包装函数,触发后自动移除自身。

要点总结

  • Vue事件系统基于发布订阅模式,事件存储于 _events 对象
  • $emit 使用 slice() 副本防止运行时回调修改问题
  • $off 支持三种移除粒度:全部、某事件、特定回调
  • 组件事件通过 on 选项传递,子组件通过 $emit 触发
  • 修饰符本质是事件对象方法的包装处理
  • $once 通过包装函数实现自动移除

📝 发现内容有误?点击此处直接编辑

← 上一篇 nextTick实现
下一篇 → 全局API实现
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库