Vue组件间数据同步刷新解决方案--全局事件总线

目录

概述

方法一:Vuex状态管理,配合组件计算属性使用

方法二:全局事件总线


概述

        Vue工程很多时候需要我们保持数据的一致性。举个例子,我在一个组件A的事件中请求后端接口修改了某个数据,并且后端接口响应我修改成功了。这时候界面上另外一个组件B也在展示该数据,这时候就需要使得这个B组件也进行显示数据的刷新,否则A组件与B组件的数据就不同步,很容易被测试提bug。

 

        如果A组件与B组件是父子关系的话,那么只需要利用父子组件之间的通讯即可完成数据的同步。但是如果这两个组件之间没有任何关系,那么如何进行跨组件之间的数据同步呢?

方法一:Vuex状态管理,配合组件计算属性使用

简要介绍一下步骤思路:

1、将项目中很多地方都需要用到的数据提取到Vuex的state中;并用getters方法返回该值; 

2、在组件中使用计算属性返回Vuex的getters获取数据;

3、组件中通过watch监听计算属性值的变化,一旦有变化,则重新赋值;

4、通过Vuex中的mutations方法修改state中数据值;

上诉步骤即可实现在任一组件中修改数据触发其他组件实时刷新的效果。但是实现过程较为繁琐。

方法二:全局事件总线

        全局事件总线是解决前端数据同步问题的一种架构思维,或者说是一种重要的编程“模式”,因为他不局限于任何一种前端框架,无论是Vue,React还是Flutter,甚至游戏编程。它都经常出现并应用。只需要学会这一套路,并通过语法变通举一反三,那么你就能轻松在各种框架上使用并解决一些列问题。而我们这里就只以Vue为例说明一下具体实现。

全局事件总线运用编程中两大模式:单例模式,观察者模式。

1、首先在任一位置新建总线类,并且该类为单例,有且只能有一个实例;以下是简单实现

class eventbus{
    constructor() {
        if (!eventbus.Instance) {
            //内存中存储所有事件的处理函数
            this.eventMap = {};
            eventbus.Instance = this;
        }
        return eventbus.Instance
    }
    /**
     * 注册事件      
     * key         事件名
     * page        组件(页面)名
     * callback    注册的事件
     */
    on(key,page,callback){
        //将函数通过事件名key,页面(组件)名的形式进行注册
        this.eventMap[key] = this.eventMap[key] || {};
        this.eventMap[key][page] = callback;
    }
    /**
     * 事件通知      
     * key         事件名
     * data        通知的数据
     * page        组件(页面)名
     */
    emit(key,data,page=null){
        if(key && this.eventMap[key]){
            if(page){
                //如果参数中有页面名(组件名),则将data通知单个页面(组件)注册的函数进行处理
                this.eventMap[key][page] && this.eventMap[key][page](data);
            }else{
                //通知该事件名下的所有页面(组件)注册的函数进行处理
                for(let sub in this.eventMap[key]) { 
                    this.eventMap[key][sub](data);
                }
            }
        }else{
            //该事件名下没有注册任何函数
        }
    },
    /**
     * 事件销毁,一般在页面(组件销毁时同步销毁)      
     * key         事件名
     * page        组件(页面)名
     */
    destroy(key,page){
        if(this.eventMap[key] && this.eventMap[key][page]){
            //删除单个页面事件
            delete this.eventMap[key][page];
        }
        if(this.eventMap[key] == {}){
            delete this.eventMap[key];
        }
    },
    /**
     * 事件销毁,销毁全部     
     * key         事件名
     * page        组件(页面)名
     */
    destroyAll(key){
        if(this.eventMap[key] == {}){
            //删除所有
            delete this.eventMap[key];
        }
    }
}
export default new eventbus()

2、在A组件中注册监听事件

<template>
  <div>{{user}}</div>
</template>

<script>
//引入全局总线类
import event from "@/Eventbus.js";
export default {
   name: "ComA",
   data () {
      return {
        user:"我是A"
      };
    },
    created() {
		//注册监听事件,事件名:changeUser,组件名:ComA
        event.on("changeUser","ComA",(data)=>{
            if(data){
                this.user = data;
            }
        })
	},
    destroyed() {
        //销毁事件
        event.destroyed("changeUser","ComA");
    }
}
</script>

3、B组件发送监听,使A组件变量一起刷新

<template>
  <div>{{user}}</div>
</template>

<script>
//引入全局总线类
import event from "@/Eventbus.js";
export default {
   name: "ComB",
   data () {
      return {
        user:"我是B"
      };
    },
    methods: {
        updateUser(){
            let data = "改成C";
            this.user = data;
            //通知所有组件(页面)刷新
            event.emit("changeUser",data);
            //只通知组件A刷新
            event.emit("changeUser",data,"ComA")
        }
    } 
}
</script>

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值