关于defineProperty和Proxy

为什么Vue3.0不再使用defineProperty实现数据监听?

链接地址

简易使用defineProperty实现双向绑定

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
 <div id="app"></div>

function vue() {
this.$data = {a:1};
this.$el = document.getElementById('app')
this.observe(this.$data)
this.render(); //初始页面中打印出1
}

vue.prototype.observe = function(data) {
var value;
var self = this;
for (var key in data) {
value = data[key]

if(typeof value == 'object') {
this.observe(value)
}
else{
Object.defineProperty(this.$data,key,{
get(){
//此处省略依赖收集
return value;
},
set(newval) {
value = newval;
self.render() //修改this.$data.a后触发方法再次渲染到页面
}
})
}
}
}

vue.prototype.render = function() {
this.$el.innerHTML = this.$data.a
}

var vm = new vue()
setTimeout(()=>{
vm.$data.a = 4444444
},2000)



Proxy的优势

  1. 直接代理整个对象,不用for in 循环了
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const input = document.getElementById('input');
const p = document.getElementById('p');
const obj = {};

const newObj = new Proxy(obj, {
get: function(target, key, receiver) {
console.log(`getting ${key}!`);
return Reflect.get(target, key, receiver);
},
set: function(target, key, value, receiver) {
console.log(target, key, value, receiver);
if (key === 'text') {
input.value = value;
p.innerHTML = value;
}
return Reflect.set(target, key, value, receiver);
},
});

input.addEventListener('keyup', function(e) {
newObj.text = e.target.value;
});

  1. Proxy可以直接监听数组的变化