vue 双向绑定

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>vue双向绑定原理分析</title></head><style>    body{        margin: 0;        padding: 0;    }</style><body><div id="app">    {{name}}</div></body><script>   //vue类    class Vue {        constructor(options={}) {            this.data = options.data            this.el = options.el            // 数据劫持            observe(this.data)            // 模版编译            compile(this.el || document.body,this)        }   }   class Ovserver {        constructor(data) {            this.data = data            this.walk(this.data)        }       walk(data) {           Object.keys(data).forEach(key=>objectDefinedDate(data,key,data[key]))       }   }   observe=(data)=>{        if (!data || typeof data !=='object') {            return        }        return new Ovserver(data)        //Object.keys(data).forEach(key=>objectDefinedDate(data,key,data[key]))   }   objectDefinedDate = (data,key,val)=> {        let dep = new Dep()        Object.defineProperty(data,key,{            enumberable:true,            configurable:true,            get:()=>{                // 添加订阅者                if (Dep.target) {                    dep.addSub(Dep.target) // Dep.target为一个全局的对象,是Watcher的实例,拥有Watcher的一切属性和方法                }                return val            },            set:(newVal)=>{                if (newVal === val) {                    return                }                val = newVal                // 通知更新                dep.notify()            }        })   }   class Dep {        constructor() {            this.subs = [] // 存放订阅者 订阅者就是观察者,即观察者实例        }        addSub(sub){            this.subs.push(sub)        }        notify() {            this.subs.forEach(sub=>sub.update()) //  调用Watcher的实例的更新方法        }   }   // 模版编译   compile =(node,vm)=> {        let reg = /\{\{(.*)\}\}/g       // 节点类型为元素       if (node.nodeType === 1) {           if (reg.test(node.innerHTML)){               let name = RegExp.$1               node.textContent = vm.data[name]               // 添加观察者               new Watcher(vm,name,function (newVal) {                   node.textContent = newVal               })           }       }   }   class Watcher {        constructor(vm,node,fn) {            this.vm = vm // vue实例            this.node = node // 绑定的节点            this.fn = fn // 更新视图的回调函数            this.value = this.get() // 触发 Object.defineProperty的get方法,而后触发添加订阅者方法        }        update(){            let value = this.vm.data[this.node]            let oldVal = this.value            if (value !== oldVal) {                this.value = value                this.fn.call(this.vm,value,oldVal)            }        }        get(){            Dep.target = this // this表示当前的Watcher的实例            let value = this.vm.data[this.node] // 触发 Object.defineProperty的get方法            Dep.target = null            return value        }   }   let el = document.getElementById('app')   const vue = new Vue({       data:{           name:'vue'       },       el:el   })   setTimeout(()=>{       vue.data.name='vue change'   },2000)</script></html>参考https://juejin.im/post/5acd0c8a6fb9a028da7cdfaf
相关文章
相关标签/搜索