这篇文章主要是为了记录笔者长期以来对于 $on 和 $emit 存在的一个误区。
看过一些博客上面将 $on 和 $emit 的使用称之为父组件监听子组件。当子组件对用户的行为做出响应时,可以向父组件 $emit 一个事件,当父组件监听到该事件时,父组件调用对应的方法来处理。
比如存在一个comp组件,它的任务是this.$emit('test') 。
<template>
<div>this is a son comp</div>
</template>
<script>
export default {
name: "comp",
mounted() {
setTimeout(()=>{
this.$emit('test')
},1000)
}
}
</script>
现在在father组件中使用comp:
<template>
<comp v-on:test="myTest1"/>
</template>
<script>
export default {
name: "father",
methods: {
myTest1(){
console.log('my test 1')
}
}
</script>
按照以前的理解:子组件向父组件emit了test事件,在父组件监听到子组件的test后,会触发myTest1 进行事件处理。
其实,这样思考在大部分情景之下都是可以说得通的:父组件监听子组件的 $emit,子组件调用 $emit后,父组件调用相应的方法进行事件处理。
但是,少数情况下,上面的说法是说不通的,观察下面的代码:
<template>
<div id="app"></div>
</template>
<script>
import Vue from "vue";
import comp from "./components/comp";
const instance = new Vue(comp)
const comp = instance.$mount()
comp.$on('test', () => {
console.log('my test 2')
})
export default {
name: "App",
}
</script>
这里的comp根本就不存在父组件,那么,也就不存在父组件监听子组件再调用函数的可能了,但是,控制台仍然会输出my test 2,这说明了什么? 并不是父组件在监听子组件,而是当前实例监听自己的自定义事件!
所以,实际情况是,comp组件通过 $emit触发了一个自定义事件,然后,comp在通过 $on 来监听这个自定义事件。
但是,当我们在父组件中使用comp组件时,我们可以将父组件的方法传递给子组件 $on监听的回调,所以看起来就像是父组件监听了子组件自定义事件并且调用相应函数进行事件处理。
在vue的官方文档中也有相关说明:
|