vue3.模仿vue3响应式原理,使用Proxy实现readonly只读

373 阅读1分钟

在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)

结果:

QQ20210421-0.png 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)

QQ20210421-1.png