8000 reactive · devazine/vue-analysis@feea478 · GitHub
[go: up one dir, main page]

Skip to content

Commit feea478

Browse files
committed
reactive
1 parent 165a376 commit feea478

File tree

3 files changed

+119
-0
lines changed

3 files changed

+119
-0
lines changed

.gitignore

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Logs
2+
logs
3+
*.log
4+
npm-debug.log*
5+
yarn-debug.log*
6+
yarn-error.log*
7+
pnpm-debug.log*
8+
lerna-debug.log*
9+
10+
node_modules
11+
dist
12+
dist-ssr
13+
dist-remote
14+
*.local
15+
16+
# Editor directories and files
17+
.vscode/*
18+
!.vscode/extensions.json
19+
.idea
20+
.DS_Store
21+
*.suo
22+
*.ntvs*
23+
*.njsproj
24+
*.sln
25+
*.sw?
26+
*.txt

1-reactive/1/example.html

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<body>
2+
<div></div>
3+
<p></p>
4+
</body>
5+
6+
<script type="module">
7+
import { setViewEffect, reactive } from './reactive.js';
8+
const div = document.querySelector('div');
9+
const p = document.querySelector('p');
10+
11+
const obj = reactive({
12+
divMsg: 'div is waiting',
13+
pMsg: 'p is waiting'
14+
});
15+
16+
setViewEffect(() => {
17+
div.innerText = obj.divMsg;
18+
})
19+
20+
setViewEffect(() => {
21+
p.innerText = obj.pMsg;
22+
})
23+
24+
setTimeout(() => {
25+
obj.divMsg = 'divMsg changes';
26+
obj.pMsg = 'pMsg changes';
27+
}, 2000);
28+
</script>

1-reactive/1/reactive.js

+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
const proxyMap = new WeakMap();
2+
const targetMap = new WeakMap();
3+
4+
let viewEffect = () => { };
5+
6+
export const setViewEffect = (fn) => {
7+
viewEffect = fn;
8+
fn();
9+
}
10+
11+
export function reactive(target) {
12+
const existingProxy = proxyMap.get(target);
13+
if (existingProxy) {
14+
// 已被代理过,直接返回缓存的代理对象
15+
// 避免重复被代理
16+
return existingProxy
17+
}
18+
19+
const proxy = new Proxy(
20+
target,
21+
baseHandlers
22+
);
23+
24+
proxyMap.set(target, proxy);
25+
return proxy
26+
}
27+
28+
const baseHandlers = {
29+
get(target, key, receiver) {
30+
const res = Reflect.get(target, key, receiver);
31+
track(target, key);
32+
return res;
33+
},
34+
set(target, key, value, receiver) {
35+
const res = Reflect.set(target, key, value, receiver);
36+
trigger(target, key, value);
37+
return res;
38+
}
39+
}
40+
41+
// 追踪
42+
const track = (target, key) => {
43+
let depsMap = targetMap.get(target)
44+
if (!depsMap) {
45+
targetMap.set(target, (depsMap = new Map()))
46+
}
47+
let dep = depsMap.get(key)
48+
if (!dep) {
49+
depsMap.set(key, (dep = new Set()));
50+
dep.add(viewEffect);
51+
console.log(`Key "${key}" is traced...`);
52+
}
53+
}
54+
55+
// 触发
56+
const trigger = (target, key, value) => {
57+
const depsMap = targetMap.get(target);
58+
if (!depsMap) {
59+
// 未被追踪过
60+
return
61+
}
62+
const viewEffects = depsMap.get(key);
63+
console.log(`Trggering effects Functions of key "${key}"...`);
64+
viewEffects.forEach(effectFn => effectFn());
65+
}

0 commit comments

Comments
 (0)
0