浅谈vue响应式原理及发布订阅模式和观察者模式
一.Vue响应式原理
首先要了解几个概念:
数据响应式:数据模型仅仅是普通的Javascript对象,而我们修改数据时,视图会进行更新,避免了繁琐的DOM操作,提高开发效率。
双向绑定:数据改变,视图改变,数据也随之改变,我们可以使用v-model在表单上创建双向数据绑定。
数据驱动是Vue最独特的特性之一:开发过程中仅需要关注数据本身,不需要关心数据是如何渲染到视图。
vue2.X中的响应式原理是基于defineProperty,兼容IE8以上版本,核心原理代码如下:
let data={ msg:'hello', count:10 } let vm={} proxyData(data) function proxyData(data){ Object.keys(data).forEach(key=>{ Object.defineProperty(vm,key,{ enumerable:true, configurable:true, writeable:true, //获取值的时候执行 get(){ console.log('get:',key,data[key]) return data[key] }, //设置值的时候执行 set(newValue){ data[key]=newValue console.log('set:',key,newValue) document.querySelector('#app').textContent=data[key] } }) }) } vm.msg //获取(get方法) hello vm.msg='hello World' //设置新属性值并渲染到页面(set方法) vm.msg //hello World
vue3.X中的响应式原理是基于Proxy,直接监听对象,而非属性,ES6中新增,IE不支持,性能由浏览器优化,性能比defineProperty要好,代码的话相比较defineProperty要简洁一些,对于多个属性的值不需要进行循环遍历处理。
let data={ msg:'hello', count:0 } //模拟 Vue 实例 let vm=new Proxy(data,{ //执行代理行为的函数 //当访问 vm 的成员会执行 get(target,key){ console.log('get,key:',key,target[key]) return target[key] }, set(target,key,newValue){ console.log('set,key:',key,newValue) if(target[key] === newValue){ return } target[key]=newValue document.querySelector("#app").textContent=target[key] } }) //测试 vm.msg='Hello World' console.log(vm.msg)
二.发布订阅模式和观察者模式
1.发布/订阅模式
这个概念有些抽象,下面举个例子说明下,家长比较关心孩子成绩,天天问孩子成绩出来没,假设可以到孩子所在班级去订阅孩子成绩,一旦考试成绩出来,相当于触发了一个事件,最后有班级的老师以短信的形式通知给家长,
不需要天天问孩子成绩出来没,家长就是事件的订阅者,老师是事件的发布者,孩子所在的班级可以假想成一个事件的中心。vue中的自定义事件都是基于发布/订阅模式的。下面模拟下发布订阅模式的运行机制:
//事件触发器 class EventEmitter(){ constructor(){ // 初始化对象{ 'click':[fn1,fn2],'change':[fn] } this.subs=Object.create(null) } //注册事件 $on(eventType,handler){ this.subs[eventType] = this.subs[eventType] || [] this.subs[eventType].push(handler) } //触发事件 $emit(eventType){ if(this.subs[eventType]){ this.subs[eventType].forEach(handler => { handler() }) } } } //测试 let em =new EventEmitter() em.$on('click',()=>{ console.log('click1') }) em.$on('click',()=>{ console.log('click2') }) em.$emit('click') //打印结果 click1,click2
二.观察者模式
观察者模式和订阅模式的区别是没有事件中心,只有发布者和订阅者,并且发布者需要知道订阅者的存在.
概念:
观察者 --Watcher
update():当事件发生时,具体要做的事情。
发布者 --Dep
subs数组:存储所有的观察者
addSub():添加观察者
notify():当事件发生,调用所有观察者的update()方法
//发布者-目标 class Dep{ constructor() { //记录所有的订阅者 this.subs=[] } //添加订阅者 addsub(sub){ if(sub && sub.update){ this.subs.push(sub) } } //发布通知 notify(){ this.subs.forEach(sub=>{ sub.update() }) } } //订阅者-观察者 class Watcher{ update(){ console.log('update') } } //测试 let dep=new Dep() let watcher=new Watcher() dep.addsub(watcher) dep.notify() //打印结果 update
总结:
观察者模式是由具体目标调度,比如当事件触发,Dep就会去调用观察者的方法,所以观察者的订阅者和发布者之间是存在依赖的。
发布订阅模式由统一调度中心调用,因此发布者和订阅者不需要知道对方的存在。
posted on 2021-08-08 18:25 メSerendipity 阅读(1744) 评论(1) 编辑 收藏 举报