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
相關文章
相關標籤/搜索