前提:props传参只适用于父子组件通信,非复杂项目又不值得使用vuex全局维护变量,因此使用eventBus实现兄弟组件通信。
EventBus是一种发布/订阅事件设计模式的实践。
在vue中适用于跨组件简单通信,不适应用于复杂场景多组件高频率通信,类似购物车等场景状态管理建议采用vuex。
优点:简单灵活,试用于不复杂的交互场景。
缺点:大量的滥用,将导致逻辑的分散,出现问题后很难定位
注意事项:
事件订阅必须在事件广播前注册;
取消事件订阅必须跟事件订阅成对出现。
实现方式:
主要是在相互通信的兄弟组件之中,都引入一个新的vue实例,然后通过分别调用这个实例的事件触发事件广播
和监听来实现通信和参数传递。
2.在list组件中每个选项绑定点击事件,并通过eventBus.$emit触发选中项。
3.在alert弹窗组件中使用eventBus.$on接收list组件传递来的选中项并控制自身显示。
4.示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="https://cdn.bootcss.com/vue/2.0.0/vue.min.js"></script>
</head>
<body>
<!-- list列表组件 -->
<script type="text/html" id="list">
<div>
<p v-for="(item,index) in listData" v-text="item" @click="eventclick($event,index)"></p>
</div>
</script>
<script>
Vue.component('list',{
template:"#list",
props:["list-data"],//父组件传递到子组件中的列表数据源
data:function(){
return {}
},
methods:{
eventclick:function(e,index){//列表组件中将每个选项的的点击事件
console.log(e)
eventBus.$emit('eventObj',{//通过$emit事件广播将变量传递出去
con:e,
isShow:true
});
}
}
})
</script>
<!-- 弹出框组件 -->
<!-- 弹出框组件使用$on接收列表组件传递过来的数据控制当前弹出框显示并展示当前数据 -->
<script type="text/html" id="alert-block">
<div v-if="obj.isShow" style="width:200px;height:200px;background: #ccc">
<p v-text="obj.msg"></p>
</div>
</script>
<script>
Vue.component('alert-block',{
template:"#alert-block",
/*当一个组件被定义, data 必须声明为返回一个初始数据对象的函数,因为组件可能
被用来创建多个实例。如果 data仍然是一个纯粹的对象,则所有的实例将共享引用
同一个数据对象!通过data 函数,每次创建一个新实例后,从而返回初始数据的一个全新副本数据对象。*/
data:function(){
return {
obj:{
msg:"",//用于接收列表组件传递过来的数据,并展示
isShow:false//用于控制弹出框组件是否显示
}
}
},
created:function(){
var that = this;
eventBus.$on('eventObj', function(item) { //监听list组件传递来的数据
console.log(item)
//将list组件传递的文本信息存储到msg变量用于弹出框组件展示
that.obj.msg = item.con.target.innerText;
//存储list组件传递过来用于显示的状态
that.obj.isShow = item.isShow;
})
},
beforeDestroy () {
//取消订阅事件
eventBus.$off('eventObj');
}
})
</script>
<!-- 页面中加载组件 -->
<div id="app">
<!-- 引入列表组件 -->
<list :list-data="listData"></list>
<!-- 引入弹出框组件 -->
<alert-block :is-show="isShow"></alert-block>
</div>
<script>
window.eventBus = new Vue();//全局定义一个eventBusB变量
var app = new Vue({
el: "#app",
data: {
listData:["事件1","事件2","事件3","事件4"],//列表组件数据源使用props传递到子组件
isShow:false//控制弹出框组件显示隐藏
},
})
</script>
</body>
</html>
实际使用中遇到的问题:在多次传递数据时,出现了数据递增,是因为弹出框组件记录了上次传递的数据,所以在每次组件销毁前取消订阅事件,也就是在弹出框组件beforeDestroy时,使用eventBus.$off(‘eventObj’);取消订阅事件。