美文网首页
vue3.0 响应式核心 proxy

vue3.0 响应式核心 proxy

作者: 我跟你蒋 | 来源:发表于2019-11-08 11:05 被阅读0次

    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

          本文链接:https://www.haomeiwen.com/subject/mceibctx.html