手写Vue2,Vue3响应式实现

83 阅读1分钟

Vue2使用defineProperty

//vue2 reacitve
let savefnNull = null;
let yui = {
    name:"yui",
    age:16
}
class Depend{
    constructor(){
        this.Setfn = new Set()
    }
    adddepend(){
        if(savefnNull){
            this.Setfn.add(savefnNull)
        }
        
    }
    notify(){
        this.Setfn.forEach(element => {
            element()
        });
    }
}
const WMapobj = new WeakMap();
function SaveObj(target,key){
    let Mapobj = WMapobj.get(target);
    if(!Mapobj){
        Mapobj = new Map()
        WMapobj.set(target,Mapobj)
    }
    let objfn = Mapobj.get(key)
    if(!objfn){
        objfn = new Depend()
        Mapobj.set(key,objfn)
    }
    return objfn;
}
function WatchFn(fn){
    savefnNull = fn;
    fn();
    savefnNull = null;
}

function defineP (obj){
    Object.keys(obj).forEach(key => {
        let value = obj[key]
        Object.defineProperty(obj,key,{
            get: function(){
                let depend = SaveObj(obj,key);
                depend.adddepend();
                return value;
            },
            set: function(newvalue){
                value = newvalue;
                let depend = SaveObj(obj,key)
                console.log('sett-----------------')
                depend.notify()
            }
        })
    })
    return obj;
}

let proxyyui = defineP(yui);
WatchFn(()=>{
    console.log(proxyyui.name)
    console.log('2'+proxyyui.name)
})
proxyyui.name = 'ss'
WatchFn(()=>{
    console.log(proxyyui.age)
    console.log('2'+proxyyui.age)
})
proxyyui.age = 15

Vue3使用Proxy

//Weakmap👉map👉{fn}
let SaveWatchFn = null
//用类存储方法
class Depend{
    constructor(){
        this.dependfn = new Set()
    }
    // adddepend(fn){
    //     this.dependfn.add(fn)
    // }
    depend(){
        if(SaveWatchFn){
            this.dependfn.add(SaveWatchFn)
        }
    }
    notify(){
        this.dependfn.forEach(element => {
            element()
        });
    }
}

//在get调用时存入依赖方法

function WatchFn(fn){
    SaveWatchFn = fn ;
    fn() ;
    SaveWatchFn = null ;
}

//收集响应式
let WatchWeakMap = new WeakMap()
function SaveProxyMap(target,key){
    let objmap = WatchWeakMap.get(target)
    if(!objmap){
        objmap = new Map()
        WatchWeakMap.set(target,objmap)
    }
    let KeyDependFn = objmap.get(key)
    if(!KeyDependFn){
        KeyDependFn = new Depend()
        objmap.set(key,KeyDependFn)
    }
    return KeyDependFn
}
let yui = {
    name:"yui",
    age:16
}
function reacitve(obj){
    return new Proxy(obj,{
        get: function (target,key,receiver) {
            let keyDepenfn = SaveProxyMap(target,key)
            keyDepenfn.depend()
            return Reflect.get(target,key,receiver)
        },
        set: function (target,key,newvalue,receiver) {
            //先代理改变再执行响应方法
            Reflect.set(target,key,newvalue,receiver)
            console.log('set---------------------------')
            let keyDepenfn = SaveProxyMap(target,key)
            keyDepenfn.notify()
        }
    })
}
let yuiproxy = reacitve(yui)

WatchFn(function (){
    console.log(yuiproxy.name)
})
WatchFn(function (){
    console.log('name改变'+ yuiproxy.name)
})
WatchFn(function (){
    console.log(yuiproxy.age)
})
WatchFn(function (){
    console.log('age改变'+ yuiproxy.age)
    console.log('age改变'+ yuiproxy.age)
})
yuiproxy.age = 1