一、vue2的Object.defineProperty()
javascript
let data = { //相当于vue中的data
msg: "",
name: '',
age: 222,
adress: {
country: 'China',
province: 'Beijing'
}
}
let vm = {} //相当于vue实例
function observe(target) {
if (typeof target !== 'object' || target === null) { return target }
Object.keys(target).forEach(key => {
defineReactive(target, key, target[key])
})
}
//把data中的所有对象都变为响应式。
function defineReactive(target, key, val) {
//通过递归的方式把嵌套对象的属性设置为响应式。
observe(val)
Object.defineProperty(target, key, {
get() {
// 在这里添加观察者对象 Dep.target 表示观察者
console.log('触发getter')
return val;
},
set(newVal) {
//处理data中对象新增属性无法监测的问题
observe(newVal)
//如果值不变则直接返回
console.log('触发setter,值为:' + newVal)
if (val !== newVal) {
val = newVal;
// 触发通知 更新视图
document.querySelector('.app').textContent = val
}
}
})
}
observe(data)
// data.age = '333'
data.name= { num: '222' }
data.name.num = '333'
二、vue3的proxy
Proxy监听的是一个对象,对这个对象上的所有操作都会被监测到,这就可以代理所有属性了。
javascript
let data = {
id: 22,
name: "henry",
address: {
country: 'China',
city: 'Beijing'
}
}
let arr = [2, 33, 10, 93, 8, 22]
//proxy 相对于Object.defineProperty,不用遍历对象的所有属性,它可以直接监听对象的所有属性。
function observe(target) {
return new Proxy(target, {
get(target, prop, receiver) {
console.log('触发了get,key为:' + prop)
return Reflect.get(...arguments)
},
set(target, key, newVal, receiver) {
console.log('触发了set,值为:' + newVal)
return Reflect.set(...arguments)
}
})
}
let proxyObj = observe(data)
console.log(data.name) // 触发了get,key为name
proxyObj.name={firstName:'tom'} // 触发了set,值为:[object Object]
proxyObj.sex = 'male'// 触发了set,值为:male
let proxyArr = observe(arr)
proxyObj.push(909) //proxy 解决了vue2 响应式中,修改数组监测不到的问题。
//proxy 解决了 Object.defineProperty 的几个问题
//1、监测不到对象深度属性改变。(vue2中通过递归实现)
//2、无法监测对对象新增属性的动作。(vue2中通过递归实现)
//3、数组的push、pop等方法无法正确监测。(vue2中通过重写数组方法,在方法中进行递归)
//4、需要遍历循环对象的所有属性。
总结:
vue3 通过proxy处理响应式 解决了vue2中使用 Object.defineProperty 的几个问题
- 监测不到对象深度属性改变。(vue2中通过递归实现)
- 无法监测对对象新增属性的动作。(vue2中通过递归实现)
- 数组的push、pop等方法无法正确监测。(vue2中通过重写数组方法,在方法中进行递归)
- 需要遍历循环对象的所有属性。