简单实现 一
问题分析 effect 函数只有一个
const bucket = new Set();
const data = {text: "hello world vue"};
const obj = new Proxy(data, {
get(target, key) {
bucket.add(effect);
return target[key];
},
set(target, key, newVal) {
target[key] = newVal;
bucket.forEach(fn => fn());
return true;
}
})
function effect() {
document.body.innerText = obj.text;
}
effect();
setTimeout(() => {
obj.text = "hello vue3";
})
简单实现 二
关系分析
一个副作用函数,读取一个对象的一个属性值
target
└── key
└── effectFn
如果有两个副作用函数,读取同一个对象的一个属性值
target
└── key
├── effectFn1
└── effectFn2
在不同的副作用函数中,读取了同一个对象的两个属性值
target
├── key1
│ └── effectFn
└── key2
└── effectFn
在不同的副作用函数中读取了两个不同对象的不同属性
target1
└── key1
└── effectFn1
target2
└── key2
└── effectFn2
问题分析,没有销毁能力
const bucket = new Set();
const data = {text: "hello world vue"};
const obj = new Proxy(data, {
get(target, key) {
if (activeEffect) {
bucket.add(activeEffect);
}
return target[key];
},
set(target, key, newVal) {
target[key] = newVal;
bucket.forEach(fn => fn());
return true;
}
})
let activeEffect;
function effect(fn) {
activeEffect = fn;
fn();
}
effect(
// 一个匿名的副作用函数
() => {
document.body.innerText = obj.text;
}
);
setTimeout(() => {
obj.text = "hello vue3";
})
简单实现 三
使用WeakMap Map Set 维护 bucket
为什么要使用 weakMap
var weakMap = new WeakMap();
var map = new Map();
(() => {
const foo = {foo: 1};
const bar = {bar: 2};
map.set(foo, 1);
weakMap.set(bar, 2);
})()
解决了,没有销毁能力的问题
const bucket = new WeakMap();
const data = {text: "hello world vue"};
const obj = new Proxy(data, {
get(target, key) {
if (!activeEffect) {
return target[key];
}
let depsMap = bucket.get(target);
if (!depsMap) {
bucket.set(target, (depsMap = new Map()));
}
let deps = depsMap.get(key);
if (!deps) {
depsMap.set(key, (deps = new Set()));
}
deps.add(activeEffect);
return target[key];
},
set(target, key, newVal) {
target[key] = newVal;
const depsMap = bucket.get(target);
if (!depsMap) return;
const effects = depsMap.get(key);
effects && effects.forEach(fn => fn());
return true;
}
})
let activeEffect;
function effect(fn) {
activeEffect = fn;
fn();
}
effect(
// 一个匿名的副作用函数
() => {
document.body.innerText = obj.text;
}
);
setTimeout(() => {
obj.text = "hello vue3";
})
简单实现 四
const bucket = new WeakMap();
const data = {text: "hello world vue"};
const track = (target, key) => { // [træk] 跟踪
if (!activeEffect) {
return
}
let depsMap = bucket.get(target);
if (!depsMap) {
bucket.set(target, (depsMap = new Map()));
}
let deps = depsMap.get(key);
if (!deps) {
depsMap.set(key, (deps = new Set()));
}
deps.add(activeEffect);
}
const trigger = (target, key) => {
const depsMap = bucket.get(target);
if (!depsMap) return;
const effects = depsMap.get(key);
effects && effects.forEach(fn => fn());
}
const obj = new Proxy(data, {
get(target, key) {
track(target, key);
return target[key];
},
set(target, key, newVal) {
target[key] = newVal;
trigger(target, key);
return true;
}
})
let activeEffect;
function effect(fn) {
activeEffect = fn;
fn();
}
effect(
// 一个匿名的副作用函数
() => {
document.body.innerText = obj.text;
}
);
setTimeout(() => {
obj.text = "hello vue3";
})