关于自定义事件$emit的一个问题
来源:8-9 event(8)

knightBUTnotYONNG
2019-03-20
Vue.prototype.$emit = function (event: string): Component {
const vm: Component = this
if (process.env.NODE_ENV !== 'production') {
const lowerCaseEvent = event.toLowerCase()
if (lowerCaseEvent !== event && vm._events[lowerCaseEvent]) {
tip(
`Event "${lowerCaseEvent}" is emitted in component ` +
`${formatComponentName(vm)} but the handler is registered for "${event}". ` +
`Note that HTML attributes are case-insensitive and you cannot use ` +
`v-on to listen to camelCase events when using in-DOM templates. ` +
`You should probably use "${hyphenate(event)}" instead of "${event}".`
)
}
}
let cbs = vm._events[event]
if (cbs) {
cbs = cbs.length > 1 ? toArray(cbs) : cbs
const args = toArray(arguments, 1)
for (let i = 0, l = cbs.length; i < l; i++) {
try {
cbs[i].apply(vm, args)
} catch (e) {
handleError(e, vm, `event handler for "${event}"`)
}
}
}
return vm
}```
$emit派发事件是for循环里调用cbs.apply(vm(子组件实例),args),但是老师为什么你说这是在父组件环境下调用的呢?
写回答
2回答
-
首先 $emit 是往当前实例上派发一个事件。
其次,通常我们说组件通讯的时候,子组件想通知父组件的时候,通常会执行 $emit 派发一个事件,但由于我们的子组件是写在父组件中的,那么这个事件侦听函数的执行作用域也就是父组件了。022019-03-20 -
前端工程师666777888
2021-04-20
cbs.apply(vm(子组件实例),args)。
按理说,cbs中的this,确实是子组件实例。
但是vue框架处理了,处理过程如下:
在this.$emit()时,会执行cbs.apply(vm(子组件实例),args),但是此时的cbs是createFnInvoker()函数中的invoker()函数并不是我们写的回调函数。在invoker()函数中,会把cbs指向我们的回调函数,在执行时会变成这样cbs.apply(null,args),已经变成null了。所以cbs中的this还是指向父组件
00
相似问题