Vue2.x子组件$emit触发父组件自定义事件的问题

Parent.vue
<template>
  <div id="parent">
    <Child @customEvent="myEvent"></Child>
  </div>
<template>
<script>
export default {
  methods: {
    myEvent (value) {
        console.log(value);
        return this;
    }
  }
}
</script>
Child.vue
<template>
  <div id="child" @click="myChildEvent">
  </div>
<template>
<script>
export default {
  methods: {
    myChildEvent () {
        this.$emit('customEvent', 1);
    }
  }
}
</script>

看了源码,组件在父组件标签上的自定义事件在构建过程中会通过Vue.prototype.$on在子组件实例vm添加_events{eventName:[invoker:fn,...]},(invoker)子组件调用Vue.prototype.$emit的时候会调用invokeWithErrorHandling,处理eventName处理对应invoker函数列表,invoker函数列表的invoker函数通过invoker.fns保存原来的处理函数,执行invoker函数的时候再次invokeWithErrorHandling执行真正的处理函数,

function invokeWithErrorHandling (handler,context,args,vm,info) {
  var res;
  try {
    res = args ? handler.apply(context, args) : handler.call(context);
  }
  ...
  return res
}

上例中最终执行的真正的处理函数是

myEvent (value) {
  console.log(value);
  return this;
}

但是调用invokeWithErrorHandling(fns, null, arguments, vm, "v-on handler")的时候context为null,handler.apply(context, args)在context为null的情况下不是应该执行全局Window对象吗,例如

var c= 6;
var a ={c:2, b:function(){alert(this.c)}}; 
a.b.apply(null); // 6

为什么Vue能够正确的指向父组件实例呢?

阅读 3.4k
1 个回答

因为在父组件初始化的时候就已经永久性的把myEvent绑定在自己身上了,这是bind的特性,不论bind多少次,都是第一次为准

image.png

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题