function isObject(target) { return typeof target === "object" && target !== null; } let targetMap = new WeakMap(); let activeEffect; let effectStack = []; let shouldTrack = true; const trackStack = []; function pauseTracking() { trackStack.push(shouldTrack); shouldTrack = false; } function enableTracking() { trackStack.push(shouldTrack); shouldTrack = true; } function resetTracking() { const last = trackStack.pop(); shouldTrack = last === undefined ? true : last; } // 新增一个被包装的push函数。 function wrappedPush(...args) { pauseTracking(); const result = Array.prototype.push.apply(this, args); resetTracking(); return result; } function track(target, key) { if (!shouldTrack) { return; } if (!activeEffect) { return; } let keyToDepMap = targetMap.get(target); if (!keyToDepMap) { keyToDepMap = new Map(); targetMap.set(target, keyToDepMap); } let effects = keyToDepMap.get(key); if (!effects) { effects = new Set(); keyToDepMap.set(key, effects); } // 建立副作用函数到包含他的集合的映射 activeEffect.deps.add(effects); effects.add(activeEffect); } function trigger(target, key) { let keyToDepMap = targetMap.get(target); if (!keyToDepMap) { return; } let effects = keyToDepMap.get(key); if (!effects) { return; } // 【特殊处理】如果是数组的length发生变化,触发所有的副作用函数。 if (Array.isArray(target) && key === "length") { keyToDepMap.forEach((effects) => { effects.forEach((effect) => { effect(); }); }); return; } // 拿到触发时的副作用函数,防止后续重复添加导致死循环 [...effects].forEach((effect) => { // 防止副作用函数中更改依赖,自己触发自己,爆栈。 if (effect === activeEffect) { return; } if (effect.options.scheduler) { // 如果有scheduler,那么运行 effect.options.scheduler(); } else { effect(); } }); } function reactive(target) { if (!isObject(target)) { console.error("target must be an object"); return; } const proxyValue = new Proxy(target, { get: (target, key) => { // 如果判断是数组的push方法直接返回包装的函数。 // 简化写法,另外的函数还有'push' 'pop', 'shift', 'unshift', 'splice'等。 if (Array.isArray(target) && key === "push") { return wrappedPush; } track(target, key); // 收集依赖 const result = Reflect.get(target, key); // 如果get的结果是一个对象,那么把它变成响应式的再返回。 if (isObject(result)) { return reactive(result); } return result; }, set: (target, key, value) => { const result = Reflect.set(target, key, value); if (result !== value) { trigger(target, key); // 触发更新 } return result; } }); return proxyValue; } function ref(rawValue) { let _value = isObject(rawValue) ? reactive(value) : rawValue; const refValue = { get value() { track(refValue, "value"); return _value; }, set value(_newValue) { if (_newValue !== _value) { //实际上要比较原始的值是否相同,而不是代理的。 _value = _newValue; trigger(refValue, "value"); } } }; return refValue; } function effect(fn, options = {}) { function reactiveEffect() { activeEffect = reactiveEffect; // 运行前先入栈 effectStack.push(activeEffect); // 运行之前,先清除依赖。 const { deps } = activeEffect; if (deps) { deps.forEach((dep) => { dep.delete(activeEffect); }); } const result = fn(); effectStack.pop(); // 运行后指向栈顶 activeEffect = effectStack[effectStack.length - 1]; return result; } // 源码用数组优化空间,这里简单用set。 reactiveEffect.deps = new Set(); reactiveEffect.options = options; if (!options.lazy) { // 不自动运行一次收集依赖。 reactiveEffect(); } return reactiveEffect; } export { reactive, ref, effect };