Vue 响应式原理
cooljser 2022-01-10 vue
vue2 中的响应式是结合数据劫持 + 发布订阅模式实现的,最简单的实现如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div class="box-1"></div>
<div class="box-2"></div>
</body>
<script src="index.js"></script>
<script>
let obj = {};
Vue({
data: obj,
tag: 'box1',
dataKey: 'one',
selector: '.box-1'
});
obj.one = 'one';
</script>
</html>
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// @ts-nocheck
const Dep = {
clientList: {},
listen: function (key, fn) {
(this.clientList[key] || (this.clientList[key] = [])).push(fn);
},
trigger: function () {
// 提取 key, 并把剩下的参数传给 fn
let key = Array.prototype.shift.call(arguments),
fns = this.clientList[key];
if (!fns || fns.length === 0) {
return false;
}
for (let i = 0, fn; fn = fns[i++];) {
fn.apply(this, arguments);
}
}
};
const Vue = function({data, tag, dataKey, selector}) {
let value = '',
el = document.querySelector(selector);
Object.defineProperty(data, dataKey, {
get: function() {
console.log('取值');
return value;
},
set: function(val) {
console.log('设置值');
value = val;
Dep.trigger(tag, val);
}
})
Dep.listen(tag, function(text) {
el.innerHTML = text;
});
}
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
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