vue3 设计一个完善的响应式系统(进击版本)

简单实现响应式系统中,代码我们简单的把函数名设置成了effect,若是函数名不叫effect,代码就出现了问题。因此我们需要提供一个注册副作用函数的机制。


// 用一个全局变量储存被注册的副作用函数
let activeEffect

// effect 函数用于注册副作用函数
function effect(fn){
  // 当调用effect注册副作用函数时,将副作用函数fn赋值给activeEffect
  activeEffect = fn
  // 执行副作用函数
  fn()
}

// 储存副作用函数的桶
const bucket = new WeakMap()

// 原始数据
const data = { text: 'hello world'}

// 对原始数据的代理
const obj = new Proxy(data,{
  // 拦截读取操作
  get(target,key){
    
    track(target,key)

    // 返回属性值
    return target[key]
  },
  // 拦截设置操作
  set(target,key,newValue){
    console.log('bucket:',bucket)
    // 设置属性值
    target[key] = newValue
   
    trigger(target,key)

    return true
  }
})

// 在 get 拦截函数内调用 track 函数追踪变化
function track(target,key){
  // 没有 activeEffect 直接 return
    if(!activeEffect) return target[key]
    // 根据 target 从 “桶” 中 取得 depsMap,它也是一个map 类型 key --》effects
    let depsMap = bucket.get(target)
    // 如果不存在 depsMap 那么新建一个Map 并与 target 关联
    if(!depsMap){
      bucket.set(target,(depsMap = new Map()))
    }
    // 再根据 key 从 depsMap 中取得 deps,它是一个 set 类型
    // 里面储存着所有与当前key 相关联的副作用函数,effects
    let deps = depsMap.get(key)
    // 如果 deps 不存在 同样新建一个set 并与 key 关联
    if(!deps){
      depsMap.set(key,(deps = new Set()))
    }
    // 最后将当前激活的副作用函数添加到“桶”
    deps.add(activeEffect)
}
// 在 set 拦截函数内调用 trigger 函数 触发变化
function trigger(target,key){
   // 根据 target 从桶中取得 depsMap,它是key --》effects
    const depsMap = bucket.get(target)
    if(!depsMap) return true
    // 根据 key 取得所有副作用函数 effects
    const effects = depsMap.get(key)
    // 执行副作用函数
    effects && effects.forEach(fn => fn())
}

// 执行副作用函数,触发读取
effect(
  // 一个匿名函数的作用函数
  ()=>{
    console.log('effect fn')
    document.body.innerText = obj.text
  }
)

// 1 秒后修改响应式数据
setTimeout(()=>{
  obj.text12 = 'hello vue3'
},1000)

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值