vue3.0 响应式核心 proxy

Proxy 是 JavaScript 2015 的一个新特性。Proxy 的代理是针对整个对象的,而不是对象的某个属性,因此不同于 Object.defineProperty 的必须遍历对象每个属性,Proxy 只需要做一层代理就可以监听同级结构下的所有属性变化,当然对于深层结构,递归还是需要进行的。此外**Proxy支持代理数组的变化。

/* based on proxy */


// 使用 Proxy 时需要定义一个代理对象 handler 来对目标进行代理操作,
// 这个对象主要有两个方法,即 get 和 set, 
// 分别为 获取和设置属性值的时候触发。同时在内部的实现需要利用到 Reflect对象
// 
// 
// 首先明确 reactive 函数接收一个参数,
// 需要对这个参数进行代理,并返回代理后的结果。
// 如果参数是对象才需要代理,否则直接返回。

// 定义一个缓存对象
const toProxy = new WeakMap(); // 保存代理后的对象

/* 返回一个被代理后的结果,通过操作这个结果可以来实现响应式, 例如视图更新 */
function reactive(target) {
    // 如果是个对象,则返回被代理后的结果,如果不是则直接返回
    if(!isObject(target)) {
        return target;
    }
    
    if(toProxy.get(target)) { // 判断对象是否已经被代理了
        return toProxy.get(target);
    }

    const handler = {
        get(target, key, receiver) {
            const proxyTarget =  Reflect.get(target, key, receiver); 
            // 相当于 return target[key]
            if(isObject(target[key])) {
                return reactive(proxyTarget);
            }

            return proxyTarget;
        },
        set(target, key, value, receiver) {
            // 只对私有属性的修改动作触发视图更新
            if(!target.hasOwnProperty(key)) {
                trigger();
            }
            return Reflect.set(target, key, value, receiver); 
            // 相当于 target[key] = value
        }
    };

    // 利用 Proxy 来代理这个对象属性
    let observed = new Proxy(target, handler);

    toProxy.set(target, observed); // 保存已代理的对象

    return observed;
}

// 提示视图需要更新
function trigger() {
    console.log('视图需要更新');
}

function isObject(param) {
    return typeof param === 'object' && param !== null;
}

你可能感兴趣的:(vue3.0 响应式核心 proxy)