发布订阅者模式以及vue中使用解析

16 篇文章 0 订阅

发布订阅模式:也称作观察者模式,定义对象间的一对多的依赖关系,当一个对象的状态发 生改变 时,所有依赖于它的对象都将得到通知;

编码中常用的场景:
//订阅事件
window.addEventListener('click',()=>{
	alert("监听到某事件")
})

//发布事件
window.click()
举个例子:B是天气预报中心,用户A想从B处获取天气预报;A就要将自己的联系方式储存到B处,当天气预报更新以后,B发送天气信息给A; 此处:存储就相当于 订阅;发信息就相当于发布;

代码实现如下:

var observer = {
	//订阅集合
	subscribes:[],
	//订阅
	subscribe:function(type,fn){
		if(!this.subscribes[type]){
			this.subscribes[type] = [];
		}
		//收集订阅者的处理
		typeof fn === 'function' && this.subscribes[type].push(fn);
	},
	//发布 可能会携带一些信息发布出去
	publish: function(){
		var type = [].shift.call(arguments),
			fns = this.subscribes[type];
		
		//不存在订阅类型,以及订阅时未传入处理回调的
		if(!fns || !fns.length){
			return;
		}
		//遍历处理调用
		for(var i = 0;i<fns.length;++i){
			fns[i].apply(this,arguments);
		}
	},
	
	//删除订阅
	remove:function(type,fn){
		//删除全部
		if(typeof type === 'undefined'){
			this.subscribes = [];
			return;
		}
		
		var fns = this.subscribes[type];
		
		//不存在的订阅类型,以及订阅时未传入处理回调的
		if(!fns || !fns.length){
			return;
		}
		
		if(typeof fn === 'undefined'){
			fns.length = 0;
			return;
		}
		
		//挨个处理删除
		for(var i = 0;i<fns.length;++i){
			if(fns[i] === fn){
				fns.splice(i,1)
			}
		}
	}
}

订阅-发布:

//订阅事件
observer.subscribe('Atemp',function(temp){
	console.log("获取的当前温度为:"+ temp +'℃')
})

//发布事件
observer.publish('Atemp',18)
Vue中使用:

vue中实现数据双向绑定:数据监听 + 订阅发布者模式(观察者模式);

class Vue{
	constructor(options) {
		this.$options = options;
	
		// 数据响应化
		this.$data = options.data;
		this.observe(this.$data);
	}
	//判断data是否是对象,是对象则遍历
	 observe(value) {
		if (!value || typeof value !== "object") {
			return;
		}
	
		// 遍历该对象
		Object.keys(value).forEach(key => {
			this.defineReactive(value, key, value[key]);
		});
	}
	//数据监听
	defineReactive(obj, key, val) {
		//递归解决数据嵌套
		this.observe(val);
		const dep = new Dep();
	
		Object.defineProperty(obj, key, {
			get() {
				//为每个属性添加依赖,订阅
				Dep.target && dep.addDep(Dep.target);
				return val;
			},
			set(newVal) {
				if (newVal === val) {
					return;
				}
				
				val = newVal;
				//发布事件,触发更新节点
				dep.notify();
			}
		});
	}


	 // Dep:用来管理watcher
	  class Dep {
	  	constructor() {
	  		// 这里存放每个依赖的1个或多个watcher
	  		this.deps = [];
	  	}
	  	// 在deps中添加一个监听器对象
	  	addDep(dep) {
	  		this.deps.push(dep);
	  	}
	  	// 通知所有依赖去更新视图
	  	notify() {
	  		this.deps.forEach(dep => dep.update());
	  	}
	  }
	  
	  //Watcher 监听器
	  class Watcher {
	  	constructor(vm, key, cb) {
	  		this.vm = vm;
	  		this.key = key;
	  		this.cb = cb;
	  		// 将当前watcher实例指定到Dep静态属性target
	  		Dep.target = this;
	  		this.vm[this.key]; // 触发getter,添加依赖
	  		Dep.target = null;
	  	}
	
	  	update() {
	  		console.log("属性更新了");
	  		//执行new Watcher传递过来的回调函数,即data值改变时,需要执行的函数。
	  		this.cb.call(this.vm, this.vm[this.key]);
	  	}
	  }
}

本文涉及知识:JS设计模式

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值