1.浅谈vue响应式原理及发布订阅模式和观察者模式

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

1.vue2.0 是根据obj.defineProperty() 获取值的时候执行 get() 设置值的时候执行set;

vue2.X中的响应式原理是基于defineProperty,兼容IE8以上版本

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)

vue3.X中的响应式原理是基于Proxy,直接监听对象,而非属性,ES6中新增,IE不支持,性能由浏览器优化,性能比defineProperty要好,代码的话相比较defineProperty要简洁一些,对于多个属性的值不需要进行循环遍历处理。

//事件触发器
        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

用构造器constructor初始化一个实例对象,$on注册事件,$emit触发事件

//发布者-目标
        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

观察者模式和订阅模式的区别是没有事件中心,只有发布者和订阅者,并且发布者需要知道订阅者的存在.

概念:

观察者 --Watcher

update():当事件发生时,具体要做的事情。

发布者 --Dep

subs数组:存储所有的观察者

addSub():添加观察者

notify():当事件发生,调用所有观察者的update()方法

观察者模式是由具体目标调度,比如当事件触发,Dep就会去调用观察者的方法,所以观察者的订阅者和发布者之间是存在依赖的。发布订阅模式由统一调度中心调用,因此发布者和订阅者不需要知道对方的存在。

你可能感兴趣的:(vue.js,观察者模式,javascript)