vue 3.0 的响应式:
3.0 的响应式是采用 es6 里面的 proxy 来实现响应式的;
用大白话理解 proxy 的响应式的话:
proxy 就是在对象之前设置了一个拦截,当该对象被访问的时候,都必须经过这层拦截。意味着你可以在这层拦截中进行各种操作。比如你可以在这层拦截中对原对象进行处理,返回你想返回的数据结构。
proxy 里面有13个参数,常用的参数 target 、handler、get、set、deleteProperty
例子:
new Proxy(data, {
// 拦截读取属性值
get(target, prop) {
return Reflect.get(target, prop)
},
// 拦截设置属性值或添加新属性
set(target, prop, value) {
return Reflect.set(target, prop, value)
},
// 拦截删除属性
deleteProperty(target, prop) {
return Reflect.deleteProperty(target, prop)
}
})
proxy.name = 'tom'
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Proxy 与 Reflect</title>
</head>
<body>
<script>
const user = {
name: 'John',
age: 12
}
/*
proxyUser是代理对象, user是被代理对象
后面所有的操作都是通过代理对象来操作被代理对象内部属性
*/
const proxyUser = new Proxy(user, {
get(target, prop) {
console.log('劫持get()', prop)
return Reflect.get(target, prop)
},
set(target, prop, val) {
console.log('劫持set()', prop, val)
return Reflect.set(target, prop, val) // (2)
},
deleteProperty(target, prop) {
console.log('劫持delete属性', prop)
return Reflect.deleteProperty(target, prop)
}
})
// 读取属性值
console.log(proxyUser === user)
console.log(proxyUser.name, proxyUser.age)
// 设置属性值
proxyUser.name = 'bob'
proxyUser.age = 13
console.log(user)
// 添加属性
proxyUser.sex = '男'
console.log(user)
// 删除属性
delete proxyUser.sex
console.log(user)
</script>
</body>
</html>
vue 2.0 的响应式
2.0 的响应式是采用 es5 里面的 Object.defineProperty 方法来实现响应式的;
核心:
- 对象: 通过 defineProperty 对对象的已有属性值的读取和修改进行劫持(监视/拦截);
- 数组: 通过重写数组更新数组一系列更新元素的方法来实现元素修改的劫持;
2.0 响应式的缺陷:
- 对象直接新添加的属性或删除已有属性, 界面不会自动更新;
- 直接通过下标替换元素或更新 length, 界面不会自动更新 arr[1] = {}
如何解决2.0 响应式的缺陷:
解决的方法官网也给出的解决之道:
1、 采用$set 、$get 、$delete