Repository navigation
Expand file tree
/
Copy pathsample.html
More file actions
95 lines (83 loc) · 3.13 KB
/
Copy pathsample.html
File metadata and controls
95 lines (83 loc) · 3.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
<!DOCTYPE html>
<html>
<head>
<title>Sample</title>
</head>
<body>
<div id="container">
<h1>Counter: <span id="counter">0</span></h1>
<h1>Next value: <span id="next-counter">1</span></h1>
<button id="increment">Increment</button>
<button id="trigger">Trigger</button>
<form>
<input type="radio" name="x" value="1" />
<input type="radio" name="x" value="2" />
<button id="submit-button" type="submit">Submit</button>
</form>
</div>
<script type="text/javascript">
class ObserverManager {
constructor({ data, refs, watch }) {
this.refs = refs;
this.watch = {};
for (const [key, watcher] of Object.entries(watch)) {
this.watch[key] = (value) => watcher(this, value);
};
this.state = this.createNestedProxy(data(), this.watch);
}
createNestedProxy(target, watch, path = []) {
const self = this;
if (typeof target !== "object" || target === null) {
return target;
}
return new Proxy(target, {
get(target, prop, receiver) {
const newPath = [...path, prop];
const value = Reflect.get(...arguments);
return self.createNestedProxy(value, watch, newPath);
},
set(target, prop, newVal, receiver) {
const newPath = [...path, prop];
const newPathStr = newPath.join(".");
const oldVal = target[prop];
if (oldVal === newVal) return;
if (newPathStr in watch) {
watch[newPathStr](newVal);
}
return Reflect.set(...arguments)
}
})
}
}
const wrapperElement = document.querySelector("#container");
const nextCounterElement = wrapperElement.querySelector("#next-counter")
const counterElement = wrapperElement.querySelector("#counter");
const incrementElement = wrapperElement.querySelector("button#increment");
const data = function() {
return {
nested: {
counter: 0,
nextCounter: 1
}
}
}
const watch = {
"nested.counter": (scope, value) => {
scope.refs.counterElement.innerText = value;
scope.state.nested.nextCounter = value + 1;
},
"nested.nextCounter": (scope, value) => {
scope.refs.nextCounterElement.innerText = value;
}
};
const wrapper = new ObserverManager({
data,
refs: { nextCounterElement, counterElement },
watch
})
incrementElement.addEventListener("click", () => {
wrapper.state.nested.counter += 1;
})
</script>
</body>
</html>