【手写vue3组合式API:shallowReactive、reactive和shallowReadonly、readonly】

9 篇文章 0 订阅
8 篇文章 2 订阅
  • shallowReactive和reactive:
// shallowReactive (浅的劫持,浅的监视,浅的响应式数据)与reactive

// 定义一个reactiveHandler处理对象
const reactiveHandler = {
    // 获取属性值
    get(target, prop) {
        const result = Reflect.get(target, prop)
        console.log('拦截了读取数据', prop, result);
        return result
    },
    // 修改属性值或是添加属性
    set(target, prop, value) {
        const result = Reflect.set(target, prop, value)
        console.log('拦截了修改数据或是添加属性', prop, value);
        return result
    },
    // 删除某个属性
    deleteProperty(target, prop) {
        const result = Reflect.deleteProperty(target, prop)
        console.log('拦截了删除数据', prop);
        return result
    }
}
// 定义一个shallowReactive,传入一个目标对象
function shallowReactive(target) {
    // 判断当前的的目标对象是不是object类型(数组/对象)
    if (target && typeof target === 'object') {
        return new Proxy(target, reactiveHandler)
    }

    // 如果传入的数据是基本类型的数据.直接返回
    return target
}

// 定义一个reactive函数,传入一个目标对象
function reactive(target) {
    // 判断当前的的目标对象是不是object类型(数组/对象)
    if (target && typeof target === 'object') {
        // 对数组或者是对象中的所有的数据进行reactive的递归处理
        // 先判断当前的数据是不是数组
        if (Array.isArray(target)) {
            // 对数组中的元素遍历,进行递归操作
            target.forEach((item, index) => {
                target[index] = reactive(item)
            })
        }
        // 判断当前的数据是不是对象
        else {
            // 对对象中的元素遍历,进行递归操作
            Object.keys(target).forEach((key) => {
                target[key] = reactive(target[key])
            })
        }
        const proxy = new Proxy(target, reactiveHandler)
        return proxy
    }

    // 如果传入的数据是基本类型的数据.直接返回
    return target
}
    <script>
		//测试用例
		
        const proxyUser1 = shallowReactive({
            name: '小米',
            car: {
                color: 'red'
            }
        })
        /*
            proxyUser1.name = '小红' // 拦截了修改数据或是添加属性 name 小红
    
            proxyUser1.name += '红'  // 拦截了读取数据 name 小红 ; 拦截了修改数据或是添加属性 name 小红红
    
            //只拦截了读  无法拦截修改数据
            proxyUser1.car.color += '颜色' // 拦截了读取数据 car {color: 'red'}
    
            // //只拦截了读  无法删除数据
            delete proxyUser1.car.color // 拦截了读取数据 car {color: 'red颜色'}
        */

        

        const proxyUser2 = reactive({
            name: '小米',
            car: {
                color: 'red'
            }
        })

          proxyUser2.name = '小红' // 拦截了修改数据或是添加属性 name 小红
   
           proxyUser2.name += '红'  // 拦截了读取数据 name 小红 ; 拦截了修改数据或是添加属性 name 小红红
   
           
           proxyUser2.car.color += '颜色' // 拦截了读取数据 car Proxy {color: 'red'} 拦截了读取数据 color red 拦截了修改数据或是添加属性 color red颜色
   
           //拦截了读  拦截了删除数据
           delete proxyUser2.car.color // 拦截了读取数据 car {color: 'red颜色'} 拦截了删除数据 color

    </script>
  • shallowReadonly和readonly:
    shallowReadonly和readonly和上面的处理类似,只是再处理对象中,不再进行删除,添加等操作,只能读取属性值
// 定义一个readonlyHandler处理对象
const readonlyHandler = {
    // 获取属性值
    get(target, prop) {
        const result = Reflect.get(target, prop)
        console.log('拦截了读取数据', prop, result);
        return result
    },
    // 修改属性值或是添加属性
    set(target, prop, value) {
        console.warn('只能读取数据,不能修改数据或添加数据');
        return true
    },
    // 删除某个属性
    deleteProperty(target, prop) {
        console.warn('只能读取数据,不能删除数据', prop);
        return true
    }
}

// 定义一个shallowReadonly,传入一个目标对象
function shallowReadonly(target) {
    // 判断当前的的目标对象是不是object类型(数组/对象)
    if (target && typeof target === 'object') {
        return new Proxy(target, readonlyHandler)
    }

    // 如果传入的数据是基本类型的数据.直接返回
    return target
}

// 定义一个readonly函数,传入一个目标对象
function readonly(target) {
    // 判断当前的的目标对象是不是object类型(数组/对象)
    if (target && typeof target === 'object') {
        if (Array.isArray(target)) {
            //readonly递归处理
            target.forEach((item, index) => {
                target[index] = readonly(item)
            })
        } else {
            Object.keys(target).forEach((key) => {
                target[key] = readonly(target[key])
            })
        }
        return new Proxy(target, reactiveHandler)
    }

    // 如果传入的数据是基本类型的数据.直接返回
    return target
}

        const proxyUser3 = shallowReadonly({
            name: '小米',
            car: ['奔驰', '宝马']
        })
        /*
        proxyUser3.name // 拦截了读取数据 name 小米
        proxyUser3.name = '小兰' // 只能读取数据,不能修改数据或添加数据
        proxyUser3.car[0] // 拦截了读取数据 car (2) ['奔驰', '宝马']
        proxyUser3.car[0] = '奥迪' // 拦截了读取数据 car (2) ['奔驰', '宝马'],但是修改操作没有拦截到
        delete proxyUser3.name // index.js:77 只能读取数据,不能删除数据 name
        */
        const proxyUser4 = readonly({
            name: '小米',
            car: ['奔驰', '宝马']
        })
        proxyUser4.name // 拦截了读取数据 name 小米
        proxyUser4.car[0] // 拦截了读取数据 car (2) ['奔驰', '宝马'] ;拦截了读取数据 0 奔驰
        proxyUser4.car[0] = '奥迪' // 拦截了读取数据 car Proxy {0: '奔驰', 1: '宝马'}; 只能读取数据,不能修改数据或添加数据
        delete proxyUser4.name // index.js:77 只能读取数据,不能删除数据 name
        delete proxyUser4.car[0] // 拦截了读取数据 car Proxy {0: '奔驰', 1: '宝马'}; 只能读取数据,不能删除数据 0
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值