Vue 響應(yīng)式布局原理解析

class Observe {
    constructor (data) {
        if (!data || typeof data !== 'object') return
        this.data = data
        this.walk()
    }
    walk () {
        Object.keys(this.data).forEach(function(val, key){
            this.propretyRactive(this.data,val,this.data[val])
        }, this)
    }
    propretyRactive(data, key, val){
        //為了保證每層的值都能添加getter,setter方法進行回調(diào)
        new Observe(val)
        var dep = new Dep()
        Object.defineProperty(data, key, {
            get (){
                if (Dep.target){
                    dep.addSub(Dep.target)
                }
                return val
            },
            set (newVal) {
                if (newVal !== val) {
                    val = newVal
                    // 為新值添加getter,setter方法
                    new Observe(val)
                    dep.notify()
                }
            }
        })
    }
}
//發(fā)布者類
class Dep {
    constructor () {
        this.subs = []
    }
    addSub (sub) {
        if (!this.subs.includes(sub)){
            this.subs.push(sub)
        }
    }
    notify () {
        this.subs.forEach(function(val){
            val.update()
        })
    }
}
Dep.target = null

//訂閱者類
class Watcher {
    constructor (vm, keys, updateCb) {
        this.vm = vm 
        this.keys = keys
        this.updateCb = updateCb
        this.value = this.get()
       
    }
    get () {
        Dep.target = this
        var value = this.vm.data
        let key = this.keys.split('.')
        //隱式調(diào)用getter方法。從而將訂閱者添加到發(fā)布者的通知列表
        key.forEach(_key=>{
            value = value[_key]
        })
        Dep.target = null
        return value
    }
    update () {
        let newVal = this.get()
        if (newVal !== this.value){
            this.value = newVal
            this.updateCb.call(this.vm)
        }

    }
}

var data = {
    test: 1,
    testObj: {
        tb1: 1
    }
}

var vm = new Observe(data)

new Watcher(vm, 'test', function(){
    console.dir('test已更新')
})
new Watcher(vm, 'testObj.tb1', function(){
    console.dir('testObj.tb1已更新')
})

data.testObj.tb1 = 2
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容