如何使用事件总线进行非父子组件之间传值
- 新建一个js文件命名为Bus.js
import Vue from 'vue'
const Bus = new Vue();
export default Bus
- 组件B
// 组件B ,监听事件send
<template>
<div>
<span>{{name}}</span>
</div>
</template>
<script>
import Bus from './bus.js'
export default {
data () {
return {
name: ''
}
},
created() {
let _this = this
// 用$on监听事件并接受数据
Bus.$on('send', (data) => {
_this.name = data
console.log(data)
})
},
methods: {}
}
</script>
- 组件A
// 组件A, 触发事件send
<template>
<div>
<input type="button" value="点击触发" @click="onClick">
</div>
</template>
<script>
import Bus from './bus.js'
export default {
data () {
return {
elValue: '我是B组件数据'
}
},
methods: {
// 发送数据
onClick() {
Bus.$emit('send', this.elValue)
}
}
}
</script>
这样就可以简单的实现一个非父子组件之间的传值了
在使用事件总线时遇到的问题
-
第一次触发的时候$on事件没有被触发
- 当我们还在页面A的时候,页面B还没生成,也就是页面B中的 created中所监听的来自于A中的事件还没有被触发。这个时候当你A中emit事件的时候,B其实是没有监听到的。
- 我们可以把A页面组件中的on事件已经触发了。
- 如果是像我们上面的代码通过事件触发的时候可以使用$nextTick()方法。将回调延迟到下次 DOM 更新循环之后执行。在修改数据之后立即使用它,然后等待 DOM 更新。它跟全局方法 Vue.nextTick 一样,不同的是回调的 this 自动绑定到调用它的实例上。
onClick() : { let _this = this // DOM 还没有更新 _this.$nextTick(function () { // DOM 现在更新了 Bus.$emit('send', this.elValue) }) }
-
后面再一次依次去触发的时候会出现,每一次都会发现好像之前的$on事件分发都没有被撤销一样,导致每一次的事件触发执行越来越多。
- 这个$on事件是不会自动清除销毁的,需要我们手动来销毁。
- 在B组件页面中添加Bus.$off来关闭
beforeDestroy(){ bus.$off('send') }
如有错误之处,欢迎指正。感谢~~~~