在Vue3中不再使用Vue2中Object.defineproperty进行属性监听,而是采用Proxy代理模式配合Reflect监听对象,proxy有两个参数,分别是target目标对象以及handle处理器,本文使用了常用的几种handler处理器方法,增删改查,并实现了简单的只读功能。
// 定义了一个readonlyHandler处理器
const readonlyHandler = {
get(target, prop) {
return Reflect.get(target, prop)
},
set(target, prop, val) {
console.warn('不能设置数据')
return true
},
deleteProperty(target, prop) {
console.warn('只能读取数据,不能删除数据')
return true
}
}
// 定义了一个浅层shallowReadonly函数
function shallowReadonly(target) {
// 判断当前target是否为对象
if (target && typeof target === 'object') {
return new Proxy(target, readonlyHandler)
}
// 不是对象或数组,直接返回
return target
}
// 定义了一个深层readonly函数
function readonly(target) {
// 判断当前target是否为对象
if (target && typeof target === 'object') {
// 判断是否是数组
if (Array.isArray(target)) {
target.forEach((val, i) => {
// 数组递归处理
target[i] = readonly(val)
})
} else {
// 对象遍历递归
Object.keys(target).forEach((key) => {
target[key] = readonly(target[key])
})
}
return new Proxy(target, readonlyHandler)
}
// 不是对象或数组,直接返回
return target
}
1.测试shallowReadonly:
const user = shallowReadonly({
name: '小明',
age: 18,
skill: [
'eat',
'drink',
'sleep'
]
})
user.name = '小红'
delete user.name
user.skill[0] = 'study'
console.log(user.skill)
结果:
2.测试readonly
结果:
const user2 = readonly({
name: '小明',
age: 18,
skill: [
'eat',
'drink',
'sleep'
]
})
user2.name = '小红'
delete user2.name
user2.skill[0] = 'study'
console.log(user2.skill)