VUE3所有类型对象的完整响应方案

/*
*原理:当触发数据读取操作时,执行副作用函数并存储到桶中
*当设置数据操作时,再将副作用函数从桶中取出并执行
*/
//用一个全局变量activeEffect存储被注册过的副作用函数
let activeEffect
//const buket=new Set()
/*
*weakMap为弱引用,不影响垃圾回收机制工作,当用户代码对一个
*对象没有引用关系时,垃圾会收器会回收该对象,避免引起栈堆的溢出
*/
const bucket=new WeakMap()
const effectStack=[]
//定义一个宏任务队列
const jobQueue=new Set()
//定义一个Promose,将一个任务添加到微任务队列
const p=Promise.resolve()
//是否正在刷新队列
let isFlushing=false
//Symbol唯一,可以作为对象属性标识符使用
const ITERATE_KEY=Symbol()
//map的键使用
const MAP_ITERATE_KEY=Symbol()
//定义一个map实例,存储原始对象到代理对象的映射
const reactiveMap=new Map()
//代表是否追踪
let shouldTrack=true
//定义一个对象,将自定义add方法添加到下面
const mutableInstrumentations={
    add(key){
        //this指向代理对象,通过raw获取原始数据对象
        const target=this.raw
        //是否元素已经存在集合中
        const hadkey=target.has(key)
        //直接使用原始数据对象的方法
        const res=target.add(key)
        if(!hadkey){
            trigger(target,key,'ADD')
        }
        return res
    },
    delete(key){
        //this指向代理对象,通过raw获取原始数据对象
        const target=this.raw
        //是否元素已经存在集合中
        const hadkey=target.has(key)
        const res=target.delete(key)
        if(hadkey){
            trigger(target,key,'DELETE')
        }
        return res
    },
    //map数据类型拥有get和set两个方法,所以需要添加这两个方法
    get(key){
        //this指向代理对象,通过raw获取原始数据对象
        const target=this.raw
        //是否元素已经存在集合中
        const had=target.has(key)
        //追踪依赖建立响应
        track(target,key)
        //直接使用原始数据对象的方法
        const res=target.get(key)
        //如果存在,返回结果,递归使用reactive返回最终的原始数据而非对象
        if(!had){
            return typeof res==='object'? reactive(res):res
        }
        return res
    },
    set(key,value){
        //this指向代理对象,通过raw获取原始数据对象
        const target=this.raw
        //是否元素已经存在集合中
        const had=target.has(key)
        //获取旧值
        const oldValue=target.get(key)
        //此处为避免污染原始数据,value必须是数据,而不能是代理对象
        const rawValue=value.raw || value
        //设置新值
        target.set(key,rawValue)
        //如果不存在,说明时add
        //只有旧值与新值不同才会触发更新
        //因为NaN===NaN为false,而NaN!==NaN为true
        if(!had){
            trigger(target,key,'ADD')
        }else if(oldValue!==value && (oldValue===oldValue || value===value)){
            trigger(target,key,'SET')
        }
    },
    forEach(callback,thisArg){
        const wrap=(val)=>typeof val==='object' ? reactive(val) : val
        const target=this.raw
        //建立响应
        track(target,ITERATE_KEY)
        //通过原始对象调用传递过去的函数
        target.forEach((v,k)=>{
            //手动实现深响应
            callback.call(thisArg,wrap(v),wrap(k),this)
        })
    },
    [Symbol.iterator]:iterationMethod,
    entries:iterationMethod,
    values:valuesIterationMethod,
    keys:keysIterationMethod,
}
//抽离独立函数
function iterationMethod(){
    const wrap=(val)=>typeof val==='object' && val!==null ? reactive(val) : val
    const target=this.raw
    //获取原始迭代器方法
    const itr=target[Symbol.iterator]()
    //建立响应
    track(target,ITERATE_KEY)
    return {
        //对象的next方法是迭代协议
        //调用原始迭代器的next方法获取value和done
        next(){
            const {value,done}=itr.next()
            return {
                //如果value不是undifined,进行包裹
                value:value?[wrap(value[0]),wrap(value[1])]:value,
                done
            }
        },
        //实现可迭代协议
        [Symbol.iterator](){
            return this
        }
    }
}
//抽离独立函数
function valuesIterationMethod(){
    const wrap=(val)=>typeof val==='object' && val!==null ? reactive(val) : val
    const target=this.raw
    //获取原始迭代器方法
    const itr=target.values()
    //建立响应
    track(target,ITERATE_KEY)
    return {
        //对象的next方法是迭代协议
        //调用原始迭代器的next方法获取value和done
        next(){
            const {value,done}=itr.next()
            return {
                value:wrap(value),
      
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值