this.$emit 真的是子传父吗

2,383 阅读1分钟

this.$emit在Vue当中真的是子传父吗?

首先说结论-不是

源码

image.png

解析

  • 首先我们可以看到$emit实际上是挂载到Vue实例原型上面的一个function
  • $emit 实际上是往Vue的当前实例去派发一个事件
  • 重要代码 let cbs = vm._events[event]-显然这一个和时间回调有关
  • 它是如何被创建的呢

initEvents的时候进行创建

image.png

  • 解析里面在vue实例上挂载了_events事件是一个对象
  • 通过vm.$options._parentListeners挂载了父亲的监听器@fn
  • 如果有监听器执行updateComponentListeners(vm, listeners)

updateComponentListeners

image.png

显然要创建一个事件监听机制-肯定要有回调函数

核心方法

createFnInvoker创建回调函数

createOnceHandler顾名思义 @click.once="add"

add方法好像是添加事件方法的样子

image.png

createFnInvoker

image.png

解析

简单来说就是创建了一个invoke函数

把我们的事件方法挂载到了invoker.fns return invoker

image.png

add方法

image.png

解析

  • target就是vue实例调用$on方法

image.png

$on方法

  • 在里面进行递归调用执行 然后push到对应的事件对象数组里面将fn方法

image.png

回头看$emit

image.png

里面进行遍历执行invokeWithErrorHandling

image.png

核心代码-给对应的事件方法传入参数并且进行执行

res = args ? handler.apply(context, args) : handler.call(context)

总结

  • 很多时候网上广为流传的东西,不一定是对的还是需要自己-去阅读源码之后才能下定论。
  • 时刻保持辩证的思想。