vue3:
- ts重写(响应式, vdom, 模板编译)
- 性能提升, 打包后代码量减少
- 调整部分API
回顾 Object.definePropery
的缺点
- 深度监听需要一次性递归
- 无法监听新增属性和删除属性(Vue.$set Vue.delete)
- 无法原生监听数组, 需要特殊处理(重写数组原型)
Proxy实现响应式
1. 基本使用
const data = {
name: 'zhangsan',
age: '20',
}
const data = ['a', 'b', 'c']
const proxyData = new Proxy(data, {
get(target, key, receiver) {
// 只处理本身(非原型的)属性
const ownKeys = Reflect.ownKeys(target)
if (ownKeys.includes(key)) {
console.log('get', key) // 监听
}
const result = Reflect.get(target, key, receiver)
return result // 返回结果
},
set(target, key, val, receiver) {
// 重复的数据,不处理
if (val === target[key]) {
return true
}
const result = Reflect.set(target, key, val, receiver)
console.log('set', key, val)
// console.log('result', result) // true
return result // 是否设置成功
},
deleteProperty(target, key) {
const result = Reflect.deleteProperty(target, key)
console.log('delete property', key)
// console.log('result', result) // true
return result // 是否删除成功
},
})
2. Reflect 作用
- 和proxy能力一一对应
- 规范化, 标准化, 函数式
- 替代掉Object上的工具函数(未来)
const obj = {a:1,b:2}
//等价
'a' in obj
Reflect.has(obj,'a')
//等价
delete obj.a
Reflect.deleteProperty(obj,'a')
//等价
Object.getOwnPropertyNames(obj) //['a','b']
Reflect.ownKeys(obj)
详细可以查阅ES6的 代理与反射
vue3 怎么用Proxy实现响应式的
// 创建响应式
function reactive(target = {}) {
if (typeof target !== 'object' || target == null) {
// 不是对象或数组,则返回
return target
}
// 代理配置
const proxyConf = {
get(target, key, receiver) {
// 只处理本身(非原型的)属性
const ownKeys = Reflect.ownKeys(target)
if (ownKeys.includes(key)) {
console.log('get', key) // 监听
}
const result = Reflect.get(target, key, receiver)
// 深度监听
// 性能如何提升的?不是一次性递归的
return reactive(result)
},
set(target, key, val, receiver) {
// 重复的数据,不处理
if (val === target[key]) {
return true
}
const ownKeys = Reflect.ownKeys(target)
if (ownKeys.includes(key)) {
console.log('已有的 key', key)
} else {
console.log('新增的 key', key)
}
const result = Reflect.set(target, key, val, receiver)
console.log('set', key, val)
// console.log('result', result) // true
return result // 是否设置成功
},
deleteProperty(target, key) {
const result = Reflect.deleteProperty(target, key)
console.log('delete property', key)
// console.log('result', result) // true
return result // 是否删除成功
},
}
// 生成代理对象
const observed = new Proxy(target, proxyConf)
return observed
}
// 测试数据
const data = {
name: 'zhangsan',
age: 20,
info: {
city: 'beijing',
a: {
b: {
c: {
d: {
e: 100,
},
},
},
},
},
}
//对数组的更改(如下标)也可以监听到
const data = ['1', '2', '3', '4']
const proxyData = reactive(data)
console.log(proxyData) //['1', '2', '3', '4']
proxyData[2] = 'test'
console.log(proxyData) //['1', '2', 'test', '4']
总结
-
深度监听. 性能更好
-
可监听新增/删除 属性
-
可监听数组变化
-
但是 Proxy 无法兼容所有的浏览器, 无法polyifll