vue3响应式系统(实现)

本文详细介绍了Vue3中的响应式原理,包括Proxy和Reflect的使用,如何实现reactive功能,以及通过WeakMap避免冗余代理对象。此外,还讨论了自动解包的机制,确保对已存在的代理对象调用reactive时返回自身。
摘要由CSDN通过智能技术生成


其实就是vue.js设计与实现的读书笔记()

前置知识

Proxy

Proxy 对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义。
Proxy.get

get(target, propKey, receiver)
  • target -目标对象
  • propKey -属性名
  • receiver -proxy实例本身
let target={
    name:"name",
    get alias(){
        console.log("----",this)//这个this绑定的就是reflect的receiver
        return this.name
    }
}

const proxy=new Proxy(target,{
    get(target,key,receiver){
        console.log(key)
        console.log("receiver",receiver)
       return Reflect.get(target,key,receiver)
    }
})
proxy.alias

请添加图片描述

Reflect

总的来说就是将Object上面一些方法,转成语言的方法,写得更合理一点。一般与Proxy搭配使用

Reflect.get(target, propertyKey[, receiver])
  • target -目标对象
  • propKey -属性名
  • receiver -如果target对象中指定了getter,receiver则为getter调用时的this值。

实现reactive

初步实现
export function reactive(target:any){
    if(!isObject(target)){
        return target
    }
    const proxy=new Proxy(target,{
    get(target,key,receiver){
       return Reflect.get(target,key,receiver)
    },
    set(target,key,receiver){
       return Reflect.set(target,key,receiver)
    },
    })
    return proxy
}

function isObject(obj:any){
    return obj !== null && typeof obj === 'object'
}

但是这样多次代理同一个对象后会多很多不同的代理对象

(vue3文档)为保证访问代理的一致性,对同一个原始对象调用 reactive() 会总是返回同样的代理对象

let obj={}
let reactive1=reactive(obj)
let reactive2=reactive(obj)
console.log(reactive1===reactive2)//false
引入weakMap 减少冗余代理对象

于是考虑到使用哈希表来存储,利用哈希表的特性(key-value唯一) 来查询之前有没有存过就创建新对象,存过直接返回之前存过的对象
使用WeakMap是因为WeakMap的键名所指向的对象,不计入垃圾回收机制(标记清除法的时候WeakMap的键指向不算),便于进行垃圾回收

let reactiveMap=new WeakMap()
export function reactive(target:any){
    if(!isObject(target)){
        return target
    }
    if(reactiveMap.get(target)){
        return reactiveMap.get(target)
    }
    const proxy=new Proxy(target,{
    get(target,key,receiver){
       return Reflect.get(target,key,receiver)
    },
    set(target,key,receiver){
       return Reflect.set(target,key,receiver)
    },
    })
    reactiveMap.set(target,proxy)
    return proxy
}

function isObject(obj:any){
    return obj !== null && typeof obj === 'object'
}
自动解包

(vue3文档) 对一个已存在的代理对象调用 reactive() 会返回其本身

这个是利用了当前对象上有没有Proxy产生的getter来判断这个对象是不是已经代理了。
首先是看这个对象的ReactiveFlags属性,如果这个对象是代理对象的话,它的getter会被拦截,返回true,如果没有就返回underfined

const ReactiveFlags="_v_IS_REACTIVE"
export function reactive(target:any){
    if(!isObject(target)){
        return target
    }
    if(reactiveMap.get(target)){
        return reactiveMap.get(target)
    }
    if(target[ReactiveFlags]) return target
    const proxy=new Proxy(target,{
    get(target,key,receiver){
        if(key===ReactiveFlags){
            return true
        }
       return Reflect.get(target,key,receiver)
    },
    set(target,key,receiver){
       return Reflect.set(target,key,receiver)
    },
    })
    reactiveMap.set(target,proxy)
    return proxy
}

function isObject(obj:any){
    return obj !== null && typeof obj === 'object'
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值