最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • Vue3响应式原理傻瓜式教程(一)——Reactive

    正文概述 掘金(DebraJohn)   2021-06-12   374

    参考教程:Vue Mastery

    理解响应式

    什么是响应式呢?举个简单的例子。

    let price = 5;
    let quantity = 2;
    let total = price * quantity; // 10
    

    现在我们将price改为6,期望total值也能自动计算更新为12。
    而这个自动计算更新,就是响应式。
    这一节我们先来谈论一下,如何触发计算更新。

    如何实现更新计算结果

    let price = 5;
    let quantity = 2;
    
    let dep = new Set() // 相当于收集方法(依赖)的仓库
    
    let effect = () => { // 计算方法
      total = price * qunatity
    }
    function track() { // 添加计算方法到仓库中
      dep.add(effect)
    }
    function trigger() { // 触发仓库中的方法
      dep.forEach(effect => effect())
    }
    

    第一步,我们需要把effect收集起来,以便于需要的时候再次调用。

    track()
    

    第二步,执行effect得到初始的结果

    effect() // total = 10
    

    第三步,当price发生改变时,再次触发已收集的方法。

    price = 6 // 此时total还是10
    trigger() // 此时得到total = 12
    

    多个属性怎么办?

    上面我们实现了一个计算方法的存储。
    实际上,每个对象会有多个属性。
    而每个属性,也都有它们各自的dep,来存储一个或多个effect。

    let product = { price: 5, quantity: 2 }
    

    所以我们建立起一个大的依赖仓库:depsMap

    const depsMap = new Map()
    

    depsMap中,用属性名(如pricequnatity)作为key,用各自的dep作为value
    那么,track方法应该这样写:

    function track(key) {
      let dep = depsMap.get(key)
      if (!dep) { // 找不到就建一个
        depsMap.set(key, (dep = new Set()))
      }
      dep.add(effect)
    }
    

    同时,trigger方法也要改写啦:

    function trigger(key) {
      let dep = depsMap.get(key)
      if (dep) {
        dep.forEach(effect => effect())
      }
    }
    

    来运行一下吧:

    let product = { price: 5, quantity: 2 }
    let total = 0
    
    let effect = () => { 
      total = product.price * product.quantity
    }
    
    track('price')
    effect() // total = 10
    
    product.price = 6 // total = 10
    trigger('price') // total = 12
    
    

    多个对象怎么办?

    上面我们实现了一个对象的响应,接下来我们来探讨下多个对象的收集方法。
    我们需要创建一个更大的仓库来存储多个object,每个object都有属于自己的depsMap。

    const targetMap = new WeakMap()
    // 为什么用WeakMap我们暂时不讨论,目前只需要知道,它的key必须是object类型
    
    function track(target, key) {
      let depsMap = targetMap.get(target)
      if (!depsMap) {  // 找不到就建一个
        targetMap.set(target, (depsMap = new Map()))
      }
      let dep = depsMap.get(key)
      if (!dep) {
        depsMap.set(key, (dep = new Set()))
      }
      dep.add(effect)
    }
    
    function trigger(target, key) {
      const depsMap = targetMap.get(target)
      if (!depsMap) return // 如果没有任何依赖,直接返回
      let dep = depsMap.get(key)
      if (dep) {
        dep.forEach(effect => effect())
      }
    }
    

    来运行一下:

    let product = { price: 5, quantity: 2 }
    let total = 0
    const depsMap = new Map()
    let effect = () => { 
      total = product.price * product.quantity
    }
    
    track('product', 'price')
    effect() // total = 10
    
    product.price = 6  // total = 10
    trigger('product', 'price') // total = 12
    

    总结

    • targetMap

    用于存放每个响应式object(所有属性)的依赖

    • depsMap

    用于存放响应式object每个属性对应的依赖

    • dep

    用于存放某个属性对应的所有依赖,当属性发生变化时,会执行依赖 Vue3响应式原理傻瓜式教程(一)——Reactive


    起源地下载网 » Vue3响应式原理傻瓜式教程(一)——Reactive

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元