第十二章 实现shallowReadonly功能

实现shallowReadonly功能

shallowReadonly: 让一个响应式数据变为只读的(浅只读)

接下来附上测试用例:

import { isReadonly,shallowReadonly } from "../reactive"

describe('shallowReadonly',()=>{
    test('should not make non-reactive properties reactive',()=>{
        // shallowReadonly: 让一个响应式数据变为只读的(浅只读)
        const props = shallowReadonly({n:{foo:1}})
        expect(isReadonly(props)).toBe(true)
        expect(isReadonly(props.n)).toBe(false)
    })

    it('warn then call set',()=>{
        console.warn = jest.fn()

        const user = shallowReadonly({
            age:10
        })

        user.age = 11

        expect(console.warn).toBeCalled()
    })
})

其实有了前面对响应式对象那一套的抽离后,现在要加入shallowReadonly功能也就很简单了(主要涉及的文件reactive.ts,baseHandlers.ts):

1 在reactive.ts中导出shallowReadonly这个方法

2 shallowReadonly中传入createReactiveObject中的shallowReadonlyHandler从我们之前baseHandlers文件中导入

3 baseHandlers中我们需要先根据条件生成对应shallowReadonlyGet

4 然后就是导出shallowReadonlyHandlers,通过封装的extend方法对readonlyHandlers进行扩展修改

下面我将按顺序给出步骤图片,并且注上解释

image.png

image.png

image.png

涉及代码文件的整体代码:

reactive.ts

import { mutableHandlers, readonlyHandlers,shallowReadonlyHandlers } from "./baseHandlers"

export const enum ReactiveFlags {
    IS_REACTIVE = "__v_isReactive",
    IS_READONLY = "__v_isReadonly"
}

export function reactive(raw){
    return createReactiveObject(raw,mutableHandlers)
}

export function readonly(raw){
    return createReactiveObject(raw,readonlyHandlers)
}

export function shallowReadonly(raw){
    return createReactiveObject(raw,shallowReadonlyHandlers)
}

export function isReactive(value){
    return !!value[ReactiveFlags.IS_REACTIVE]
}

export function isReadonly(value){
    return !!value[ReactiveFlags.IS_READONLY]
}

function createReactiveObject(target,baseHandlers){
    return new Proxy(target,baseHandlers)
}

baseHandler.ts

import { extend, isObject } from "../shared"
import { track, trigger } from "./effect"
import { reactive, ReactiveFlags, readonly } from "./reactive"

const get = createGetter()
const set = createSetter()
const readonlyGet = createGetter(true)
const shallowReadonlyGet = createGetter(true,true)

function createGetter(isReadonly = false,shallow = false){
    return function get(target,key){

        if(key === ReactiveFlags.IS_REACTIVE) {
            return !isReadonly
        }else if(key === ReactiveFlags.IS_READONLY) {
            return isReadonly
        }

        const res = Reflect.get(target,key)

        // 如果shallow为true
        if(shallow){
            return res
        }

        // 看看 res 是不是 object
        if(isObject(res)){
            return isReadonly ? readonly(res) : reactive(res)
        }

        if(!isReadonly) {
            track(target,key)
        }

        return res
    }
}

function createSetter() {
    return function set(target,key,value){
        const res = Reflect.set(target,key,value)

        trigger(target,key)
        return res
    }
}

export const mutableHandlers = {
    get:get,
    set:set
}

export const readonlyHandlers = {
    get:readonlyGet,
    set(target,key,value){
        console.warn(`key:${key} set 失败 因为 target 是readonly`,target)
        return true
    }
}

export const shallowReadonlyHandlers = extend({},readonlyHandlers,{
    get:shallowReadonlyGet
})
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值