Vue3.0响应式原理

10 月 5 日凌晨,Vue3.0 框架的作者兼核心开发者尤雨溪公布了尚处于 Pre-Alpha 状态的 Vue3.0 源码 https://github.com/vuejs/vue-next

141547_4LK0_2720166.jpg

体验

首先打开上面源码地址,执行npm install,然后npm run devnpm run build
4968498649684

上面标红的文件,就是 Vue3.0 预览版生成的文件。

1984984984

首先感受一下预览版

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
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>

<body>
<div id="app"></div>
<script src="./dist/vue.global.js"></script>
<script >
const App = {
template: '{{count}}',
data() {
return {
count: 1
}
}
}
let container = document.getElementById('app');
let _proxy = Vue.createApp().mount(App, container);
setTimeout(() => {
_proxy.count = 100;
console.log(_proxy)
}, 1000)
</script>
</body>

</html>

496494

可以看到数据已经响应式变化,_proxy就是代理响应式数据侦测的对象

Proxy 如何实现响应数据变化

Vue3.0 核心操作在

45646541654156451

  • 关于WeakMap的详解,可以参考后面的文章 ES6 Map、WeakMap详解
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
//核心基于Proxy
//Vue.reactive

const toProxy = new WeakMap(); //存放代理后的对象
const toRaw = new WeakMap(); //存放代理前的对象

function trigger() {
console.log("触发视图更新");
}

function isObject(target) {
return typeof target === "object" && target != null;
}

function reactive(target) {
if (!isObject(target)) {
return target;
}

if (toProxy.get(target)) {
//如果代理表中已经存在了,就把当前结果返回
return toProxy.get(target);
}
if (toRaw.has(target)) {
//如果对象已被代理过了,就把对象原封不动返回
return target;
}
const handlers = {
//触发的方法
set(target, key, value, receiver) {
if (target.hasOwnProperty(key)) {
//只有是私有属性时,才会触发更新
trigger();
}
return Reflect.set(target, key, value, receiver);
//https://www.jianshu.com/p/4a5eca0536c3 Reflect详解
},
get(target, key, receiver) {
const res = Reflect.get(target, key, receiver);
if (isObject(target[key])) {
//因为Proxy只能做一层代理,如果子元素还是对象,那么递归继续代理
return reactive(res);
}
return res;
},
deleteProprety(target, key) {
return Reflect.deleteProprety(target, key);
}
};
let observed = new Proxy(target, handlers);
toProxy.set(target, observed); //原对象 :代理后结果
toRaw.set(observed, target);
return observed;
}

let obj = {
name: "yuwangi",
ary: [1, 2, 3]
};

let _proxy = reactive(obj);

_proxy.name = "hahah";

console.log(obj);

_proxy.ary.push(4);

console.log(obj);

运行结果:
416541651