zoukankan      html  css  js  c++  java
  • 写一个简单vue 中间件,$emit、$on

    前言

    使用过vue的同学大多数都知道$emit 与$on的使用。我们仅仅知道使用,有时候是完全不够的。现在我就带领大家写一个简单类似于vue空实例的中间件。

    非父子组件的通信

    非父子组件的通信vue官网给出这样的解决方案。
    有时候,非父子关系的两个组件之间也需要通信。在简单的场景下,可以使用一个空的 Vue 实例作为事件总线:

    var bus = new Vue()
    // 触发组件 A 中的事件
    bus.$emit('id-selected', 1)
    // 在组件 B 创建的钩子中监听事件
    bus.$on('id-selected', function (id) {
      // ...
    })
    

    简单例子

    下面是一个很简单的例子

    //工具
    var myBus = (function() {
    	var clienlist = {},
    		addlisten, trigger, remove;
    	/**
    	 * 增加订阅者
    	 * @key {String} 类型
    	 * @fn {Function} 回掉函数
    	 * */
    	addlisten = function(key, fn) {
    		if(!clienlist[key]) {
    			clienlist[key] = [];
    		}
    		clienlist[key].push(fn);
    	};
    	/**
    	 * 发布消息
    	 * */
    	trigger = function() {
    		var key = [].shift.call(arguments), //取出消息类型
    			fns = clienlist[key]; //取出该类型的对应的消息集合
    		if(!fns || fns.length === 0) {
    			return false;
    		}
    		for(var i = 0, fn; fn = fns[i++];) {
    			fn.apply(this, arguments);
    		}
    	};
    	/**
    	 * 删除订阅
    	 * @key {String} 类型
    	 * @fn {Function} 回掉函数
    	 * */
    	remove = function(key, fn) {
    		var fns = clienlist[key]; //取出该类型的对应的消息集合
    		if(!fns) { //如果对应的key没有订阅直接返回
    			return false;
    		}
    		if(!fn) { //如果没有传入具体的回掉,则表示需要取消所有订阅
    			fns && (fns.length = 0);
    		} else {
    			for(var l = fns.length - 1; l >= 0; l--) { //遍历回掉函数列表
    				if(fn === fns[l]) {
    					fns.splice(l, 1); //删除订阅者的回掉
    				}
    			}
    		}
    	};
    	return {
    		$on: addlisten,
    		$emit: trigger,
    		$off: remove
    	}
    })();
    //组件一
    Vue.component('vv-count', {
    	props: ["count"],
    	template: '<div>
                     <span>{{count}}</span><button @click="handelClick" type="button">计算</button>
                   </div>',
    	methods: {
    		handelClick() {
    			console.log('vv-count总计:', this.count);
    
    			if(vue_bus){
    			 	//触发发布--使用vue
    			    bus.$emit("vv_count", this.count,'这是使用vue的')
    			 }else{
    			 	//触发发布--使用自己的
    			    myBus.$emit("vv_count", this.count,'这是自己写的')
    			 }
    		}
    	}
    });
    //组件二
    Vue.component('vv-count1', {
    	props: ["count"],
    	template: '<div>
                     <span>{{count}}</span><button @click="handelClick" type="button">计算</button>
                   </div>',
    	methods: {
    		handelClick() {
    			console.log('vv-count1总计:', this.count);
    			 
    			 if(vue_bus){
    			 	//触发发布
    			    bus.$emit("vv_count", this.count)
    			 }else{
    			 	//触发发布
    			    myBus.$emit("vv_count", this.count)
    			 }
    			
    		}
    	}
    });
    
    var vue_bus=true;// true:使用vue的事件总线,false:使用自己的事件总线
    
    
    if(vue_bus){
    	//中间件
    	var bus = new Vue();
    	//使用vue的事件总线--订阅
    	bus.$on("vv_count", function() {
    		console.log("使用bus发布的参数==", arguments);
    	});
    }else{
    	//使用自己的事件总线--订阅
    	myBus.$on("vv_count", function() {
    		console.log("使用myBus发布的参数==", arguments);
    	});
    }
    
    
    new Vue({
    	el: "#app"
    });
    

    上面代码可以使用vue_bus=true 或者false 相互切换进行看效果。如图所示:


    如果想看更加详细的讲解请预览发布-订阅模式 or 发布-订阅模式

    总结

    vue中的发布订阅跟自己写的发布订阅原理是相同的,希望大家能够get到知识。

    打赏通道--我觉得不会有打赏。

  • 相关阅读:
    剑指OFFER——顺时针打印矩阵
    剑指OFFER——合并两个有序的链表
    剑指OFFER——正则表达式匹配
    剑指OFFER——调整数组顺序使奇数位于偶数前面
    剑指offer——矩阵覆盖(斐波那契变形)
    剑指OFFER的跳台阶问题
    2016携程测试实习生笔试编程题
    大数乘法——2016开发实习生腾讯模拟笔试编程题
    53. Maximum Subarray
    Redis和Memcached的区别【转】
  • 原文地址:https://www.cnblogs.com/xiaoxiaokun/p/8836506.html
Copyright © 2011-2022 走看看