第九章 实现isReactive和isReadonly

实现isReactive和isReadonly

isReactive实现

先上测试用例(其实这个测试用例也是reactive.spec.ts中追加的两个):

import { isReactive, reactive } from "../reactive"

describe('reactive',()=>{
    it('happy path',()=>{
        const original = {foo:1}
        const observed = reactive(original)
        expect(observed).not.toBe(original)
        expect(observed.foo).toBe(1)
        expect(isReactive(observed)).toBe(true)
        expect(isReactive(original)).toBe(false)
    })
})

实现:

1 reactive.ts中导出isReactive方法

2 利用isReactive传入的对象,调用对象中特定设置的一个属性__v_isReactive,如果这个对象是响应式对象,就会走get函数

3 我们可以在get函数中判断key值,如果为__v_isReactive的话,就返回他不是readonly

image.png

image.png

优化

对于这种__v_isReactive属性,我们可以使用枚举,让我们在别的地方降低书写错误

修改如下

image.png

image.png

isReadonly实现

有了isReactive的实现,那isReadonly也就水到渠成了,测试案例

image.png

实现上基本和isReactive一样

reactive.ts

image.png

image.png

最终:

reactive.ts代码

import { mutableHandlers, readonlyHandlers } 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 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)
}

baseHandlers.ts

import { track, trigger } from "./effect"
import { ReactiveFlags } from "./reactive"

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

function createGetter(isReadonly = false){
    return function get(target,key){
        const res = Reflect.get(target,key)

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

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

        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
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值