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

Lines changed: 26 additions & 0 deletions
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

Lines changed: 28 additions & 0 deletions
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

Lines changed: 65 additions & 0 deletions
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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy