vue reactive基本obj类和shallowReactive类传入实现

//类型判断函数
const isObject = (val) => val !== null && typeof val === 'object';
const isArray = Array.isArray;
const isSymbol = (val) => typeof val === 'symbol'; 
const objectToString = Object.prototype.toString;
function isRef(r) {
    return Boolean(r && r.__v_isRef === true);
}
const isString = (val) => typeof val === 'string';
//传入的key 必须是一个string类型的数据
const isIntegerKey = (key) => isString(key) &&key !== 'NaN' &&key[0] !== '-' &&'' + parseInt(key, 10) === key;
const hasOwnProperty = Object.prototype.hasOwnProperty;
const hasOwn = (val, key) => hasOwnProperty.call(val, key);

function getTargetType(value) {
    return value["__v_skip" /* SKIP */] || !Object.isExtensible(value)
        ? 0 /* INVALID */
        : targetTypeMap(toRawType(value));
}
function targetTypeMap(rawType) {
    switch (rawType) {
        case 'Object':
        case 'Array':
            return 1 /* COMMON */;
        case 'Map':
        case 'Set':
        case 'WeakMap':
        case 'WeakSet':
            return 2 /* COLLECTION */;
        default:
            return 0 /* INVALID */;
    }
}
const toRawType = (value) => {
    // extract "RawType" from strings like "[object RawType]"
    return toTypeString(value).slice(8, -1);
};
const toTypeString = (value) => objectToString.call(value);


const reactiveMap = new WeakMap();
const set =  createSetter();
//这样返回到 set 的时候就是一个函数

function toRaw(observed) {
    const raw = observed && observed["__v_raw" /* RAW */];
    return raw ? toRaw(raw) : observed;
}
function createSetter(shallow = false) {

    //set 拦截操作  传入true时
    return function set(target, key, value, receiver) {
        let oldValue = target[key];
        console.log(target,'target')  // {a: 2}a: 2[[Prototype]]: Object
        console.log(key,'key')
        console.log(value,'value')
        console.log(receiver,'receiver')
        console.log(oldValue,'oldValue')

        // !!!这一步是shallowReactive 和 reactive 区别
        //因为它们传入 shallow的值不同
        if (!shallow) {
            //reactive createSetter()没有传参,所以shallow默认参数为false,
            //所以走这个判断  把value 和oldValue 都转换为原始值
            value = toRaw(value);
            oldValue = toRaw(oldValue);
            console.log(!isArray(target),'!isArray(target)')   //true
            console.log(isRef(oldValue),'isRef(oldValue)')    //false
            console.log(!isRef(value),'!isRef(value)')      //true
            //所以这个判断并没有为真,所以value的值也没有付给oldValue
            if (!isArray(target) && isRef(oldValue) && !isRef(value)) {
                oldValue.value = value;
                return true;
            }
        }
        //hadKey 为false  
        const hadKey = isArray(target) && isIntegerKey(key)
            ? Number(key) < target.length
            : hasOwn(target, key);
        console.log(hadKey,'handKey')    //控制输出为真
        //执行Reflect.set()操作
        const result = Reflect.set(target, key, value, receiver);

        console.log(result,'Reflect.set()后的值')
        // don't trigger if target is something up in the prototype chain of original
        //如果目标是原型链中的某个东西,则不要触发 所以我们需要调用toRaw() 转换为原始数据,这个地方是做异常处理的
        console.log(target)
        console.log(Object.getPrototypeOf(target),'原型链')
        // console.log(target === toRaw(receiver),'2')
        // console.log(target === toRaw(receiver),'2')
        // console.log(target === toRaw(receiver),'2')   //这个地方执行了 toRaw()函数改变了receiver 就会被Proxy get()所拦截
        if (target === toRaw(receiver)) {
            console.log('true login')
            if (!hadKey) {
                console.log(!hadKey,'!hadKey')
                trigger(target, "add" /* ADD */, key, value);
            }
            else if (hasChanged(value, oldValue)) {
                console.log('has changed')
                trigger(target, "set" /* SET */, key, value, oldValue);
            }
        }
        return result;
    };
}
const hasChanged = (value, oldValue) => !Object.is(value, oldValue);
const get = createGetter();
const mutableHandlers = {
    get, //get 和之前readOnly get方法差不多
    set,  //先实现set  
    deleteProperty,  //实现set的基础上继续实现deleteProperty
    has,   //实现 has功能
    ownKeys
};
const ITERATE_KEY = Symbol('iterate');
function ownKeys(target) {
    track(target, "iterate" , isArray(target) ? 'length' : ITERATE_KEY);
    return Reflect.ownKeys(target);
}
const arrayInstrumentations =  createArrayInstrumentations();
// 创建数组仪表清单
function createArrayInstrumentations() {
    const instrumentations = {};
    ['includes', 'indexOf', 'lastIndexOf'].forEach(key => {
        instrumentations[key] = function (...args) {
            const arr = toRaw(this);
            for (let i = 0, l = this.length; i < l; i++) {
                track(arr, "get" /* GET */, i + '');
            }
            // we run the method using the original args first (which may be reactive)
            const res = arr[key](...args);
            if (res === -1 || res === false) {
                // if that didn't work, run it again using raw values.
                return arr[key](...args.map(toRaw));
            }
            else {
                return res;
            }
        };
    });
    ['push', 'pop', 'shift', 'unshift', 'splice'].forEach(key => {
        instrumentations[key] = function (...args) {
            pauseTracking();

            //拦截元素属性value的proxy
            const res = toRaw(this)[key].apply(this, args);
            resetTracking();
            return res;
        };
    });
    return instrumentations;
}
function pauseTracking() {
    trackStack.push(shouldTrack);
    shouldTrack = false;
}
function resetTracking() {
    const last = trackStack.pop();
    shouldTrack = last === undefined ? true : last;
}
const isNonTrackableKeys = makeMap(`__proto__,__v_isRef,__isVue`);
function makeMap(str, expectsLowerCase) {
    const map = Object.create(null);
    const list = str.split(',');
    for (let i = 0; i < list.length; i++) {
        map[list[i]] = true;
    }
    return expectsLowerCase ? val => !!map[val.toLowerCase()] : val => !!map[val];
}
function track(target, type, key) {

    //这个地方实际上是返回了的,可能这个要在传入es6新增加的 weak 类型的obj 才会触发
    if (!isTracking()) {
        return;
    }
    let depsMap = targetMap.get(target);
    if (!depsMap) {
        targetMap.set(target, (depsMap = new Map()));
    }
    let dep = depsMap.get(key);
    if (!dep) {
        depsMap.set(key, (dep = createDep()));
    }
    const eventInfo = { effect: activeEffect, target, type, key }
        ;
    trackEffects(dep, eventInfo);
}
let activeEffect;
let shouldTrack = true;
const trackStack = [];
function isTracking() {
    return shouldTrack && activeEffect !== undefined;
}
function trackEffects(dep, debuggerEventExtraInfo) {
    let shouldTrack = false;
    if (effectTrackDepth <= maxMarkerBits) {
        if (!newTracked(dep)) {
            dep.n |= trackOpBit; // set newly tracked
            shouldTrack = !wasTracked(dep);
        }
    }
    else {
        // Full cleanup mode.
        shouldTrack = !dep.has(activeEffect);
    }
    if (shouldTrack) {
        dep.add(activeEffect);
        activeEffect.deps.push(dep);
        if (activeEffect.onTrack) {
            activeEffect.onTrack(Object.assign({
                effect: activeEffect
            }, debuggerEventExtraInfo));
        }
    }
}
//这一次没有传入参数,默认就都为false
function createGetter(isReadonly = false, shallow = false) {
    // get 拦截操作
    return function get(target, key, receiver) {
        console.log('-----拦截------')  //控制台输出12次
        console.log(target,'target')
        console.log(key,'key')
        console.log(receiver,'receiver')
        console.log(trackStack,'栈列表')
        if (key === "__v_isReactive" /* IS_REACTIVE */) {
            console.log('key === _v_isReactive 已经被执行返回了')
            return !isReadonly;
        }
        else if (key === "__v_isReadonly" /* IS_READONLY */) {
            console.log('key === _v_isReadonly 已经被执行返回了')
            return isReadonly;
        }
        else if (key === "__v_raw" /* RAW */ &&
            receiver ===
                (isReadonly
                    ? shallow
                        ? shallowReadonlyMap
                        : readonlyMap
                    : shallow
                        ? shallowReactiveMap
                        : reactiveMap).get(target)) {
                            console.log(reactiveMap,'reactiveMap')
                            console.log('走到这一步')
            return target;
        }
        const targetIsArray = isArray(target);
        if (!isReadonly && targetIsArray && hasOwn(arrayInstrumentations, key)) {
            console.log(key,'key为数组操作方法')
            console.log(arrayInstrumentations,'arrayInStrumentations')
            return Reflect.get(arrayInstrumentations, key, receiver);
        }
        //拦截
        const res = Reflect.get(target, key, receiver);
        console.log(res,'Reflect.get()操作')
        if (isSymbol(key) ? builtInSymbols.has(key) : isNonTrackableKeys(key)) {
            return res;
        }
        if (!isReadonly) {
            track(target, "get" /* GET */, key);
        }
        if (shallow) {
            return res;
        }
        if (isRef(res)) {
            // ref unwrapping - does not apply for Array + integer key.
            const shouldUnwrap = !targetIsArray || !isIntegerKey(key);
            return shouldUnwrap ? res.value : res;
        }
        if (isObject(res)) {
            // Convert returned value into a proxy as well. we do the isObject check
            // here to avoid invalid value warning. Also need to lazy access readonly
            // and reactive here to avoid circular dependency.
            return isReadonly ? readonly(res) : reactive(res);
        }
        return res;
    };
}
function has(target, key) {
    const result = Reflect.has(target, key);
    if (!isSymbol(key) || !builtInSymbols.has(key)) {
        track(target, "has" /* HAS */, key);
    }
    return result;
}
//deleteProperty 函数看起来很简单
function deleteProperty(target, key) {
    const hadKey = hasOwn(target, key);
    const oldValue = target[key];
    const result = Reflect.deleteProperty(target, key);

    console.log(result,'result')   //true
    console.log(hadKey,'hadKey')   //true
    //函数就会执行trigger() 函数
    if (result && hadKey) {
        trigger(target, "delete", key, undefined, oldValue);
    }
    return result;
}
const targetMap = new WeakMap();
function trigger(target, type, key, newValue, oldValue, oldTarget) {
    const depsMap = targetMap.get(target);
    // console.log(targetMap,'targetMap的值')
    console.log(depsMap,'depsMap 的值')   //undefined
    if (!depsMap) {
        // never been tracked
        //直接返回 没有继续执行下面的代码
        return;
    }
    let deps = [];
    if (type === "clear" /* CLEAR */) {
        // collection being cleared
        // trigger all effects for target
        deps = [...depsMap.values()];
    }
    else if (key === 'length' && isArray(target)) {
        depsMap.forEach((dep, key) => {
            if (key === 'length' || key >= newValue) {
                deps.push(dep);
            }
        });
    }
    else {
        // schedule runs for SET | ADD | DELETE
        if (key !== void 0) {
            deps.push(depsMap.get(key));
        }
        // also run for iteration key on ADD | DELETE | Map.SET
        switch (type) {
            case "add" /* ADD */:
                if (!isArray(target)) {
                    deps.push(depsMap.get(ITERATE_KEY));
                    if (isMap(target)) {
                        deps.push(depsMap.get(MAP_KEY_ITERATE_KEY));
                    }
                }
                else if (isIntegerKey(key)) {
                    // new index added to array -> length changes
                    deps.push(depsMap.get('length'));
                }
                break;
            case "delete" /* DELETE */:
                if (!isArray(target)) {
                    deps.push(depsMap.get(ITERATE_KEY));
                    if (isMap(target)) {
                        deps.push(depsMap.get(MAP_KEY_ITERATE_KEY));
                    }
                }
                break;
            case "set" /* SET */:
                if (isMap(target)) {
                    deps.push(depsMap.get(ITERATE_KEY));
                }
                break;
        }
    }
    const eventInfo = { target, type, key, newValue, oldValue, oldTarget }
        ;
    if (deps.length === 1) {
        if (deps[0]) {
            {
                triggerEffects(deps[0], eventInfo);
            }
        }
    }
    else {
        const effects = [];
        for (const dep of deps) {
            if (dep) {
                effects.push(...dep);
            }
        }
        {
            triggerEffects(createDep(effects), eventInfo);
        }
    }
}
function reactive(target) {
    // if trying to observe a readonly proxy, return the readonly version
    //如果已经是readOnly对象了,就直接返回就行了,不需要再进行reactive处理
    if (target && target["__v_isReadonly" /* IS_READONLY */]) {
        return target;
    }
    // return createReactiveObject(target, false, mutableHandlers, mutableCollectionHandlers, reactiveMap);
    //一般不走上边那个 所以下面只要传一个baseHandeler 就行了
    return createReactiveObject(target, false, mutableHandlers, reactiveMap);
}


// function shallowReactive(target) {
//     return createReactiveObject(target, false, shallowReactiveHandlers, shallowCollectionHandlers, shallowReactiveMap);
// }


// baseHandlers  传入的值 为 mutableHandlers
function createReactiveObject(target, isReadonly, baseHandlers, proxyMap) {
    //传入isReadonly 值为true,判断传入的值是否为除Null 以外的Object对象,如果不是的话就会弹出错误,
    if (!isObject(target)) {
        {
            console.warn(`value cannot be made reactive: ${String(target)}`);
        }
        return target;
    }
    // target is already a Proxy, return it.
    // exception: calling readonly() on a reactive object
    // 这些条件都满足的话说明传入的已经是一个reactive对象了 ,直接return 返回即可
    if (target["__v_raw" /* RAW */] &&!(isReadonly && target["__v_isReactive" /* IS_REACTIVE */])) {
        return target;
    }
    
    // 初始化时proxyMap 为空 
    console.log(proxyMap,'proxymap')    //WeakMap { <items unknown> } proxymap 
    const existingProxy = proxyMap.get(target);   //获取到的值为undefined 
    if (existingProxy) {
        return existingProxy;
    }
    // only a whitelist of value types can be observed.
    const targetType = getTargetType(target); //target为object时  targetType 为 1 如果tarfetType 为0时 数据类型不对
    if (targetType === 0 /* INVALID */) {
        return target;
    }
    console.log(targetType,'targetType')
    const proxy = new Proxy(target, baseHandlers);
    proxyMap.set(target, proxy);
    return proxy;
}


// var result = reactive([{a:2},2,3])
// console.log(result[0],'取到的值')  //Proxy {a: 2} "取到的值"
// var result = reactive([1,2,3])
// console.log(result[0],'取到的值')  // 1 "取到的值"

// var result = reactive([1,2,3])
// console.log(result,'修改之前的值')  
// result.shift()
// console.log(result,'修改之后的值')

var result = reactive({a:2})
console.log(result,'修改之前的值')  
result.a=3
console.log(result,'修改之后的值')

控制台输出 

const shallowReactiveMap = new WeakMap();
const shallowGet =  createGetter(false, true);
const shallowSet =  createSetter(true);
const shallowReactiveHandlers = extend({}, mutableHandlers, {
    get: shallowGet,  //重写get和 set这两个方法
    set: shallowSet
});
function shallowReactive(target) {
    return createReactiveObject(target, false, shallowReactiveHandlers, shallowReactiveMap);
}


var result = shallowReactive({a:2})
console.log(result,'修改之前的值')  
result.a=3
console.log(result,'修改之后的值')

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值