使用eventBus 实现兄弟组件间通信

前提: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’);取消订阅事件。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值