Vue Mastery – 响应式原理

Vue Mastery – 响应式原理Vue3Reactivityletprice=5letquantity=2lettotal=0letdep=newSet()leteffect=()={total=price*quantity}

Vue3 Reactivity

let price = 5
let quantity = 2
let total = 0

let dep = new Set()

let effect = () => { 
   
    total = price * quantity
}

function track() { 
   
    dep.add(effect)
}

function trigger() { 
   
    dep.forEach(effect => effect())
}

track()
effect()
trigger()
  • track 依赖收集
  • trigger 更新依赖

通常我们有多个属性,如何监听多个属性的依赖呢?

使用一个图来保存属性和它相关的依赖函数。

const depsMap = new Map()

function track(key) { 
   
    let dep = depsMap.get(key) // 得到属性相关的依赖集合
    if (!dep) { 
   
        depsMap.set(key, (dep = new Set()))
    }

    dep.add(effect) // Set不会重复添加
}

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

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

let effect = () => { 
   
    total = product.price * product.quantity
}

track('quantity')
effect() // 此时total为10
product.quantity = 3
trigger() // 此时total为15

如何建立一个响应式对象和其属性和其依赖项的关系呢?

使用WeakMap,将这个对象作为key值,而其value值,则是属性和依赖的图。

在这里插入图片描述

const targetMap = new WeakMap()
    function track(target, key) { 
   
        let depsMap = targetMap.get(target)
        if (!depsMap) { 
   
            targetMap.set(target, (depsMap = new Map())) // 注意等号返回的是 new Map()
        }
        let deps = depsMap.get(key)
        if (!deps) { 
   
            depsMap.set(key, deps = new Set())
        }
        deps.add(effect)
    }

    function trigger(target, key) { 
   
        const depsMap = targetMap.get(target)
        if (!depsMap) { 
   
            return
        }

        const deps = depsMap.get(key)
        if (deps) { 
   
            deps.forEach(effect => { 
   
                effect()
            })
        }
    }

    let product = { 
   
        price: 5,
        quantity: 2
    }
    let total = 0
    let effect = () => { 
   
        total = product.price * product.quantity
    }

    track(product, 'quantity')
    effect()
    console.log(total) // 10
    product.quantity = 3
    trigger(product, 'quantity')
    console.log(total) // 15

但是,我们还无法让effect自动执行。还需要完善。

Proxy and Reflect

在这里插入图片描述
真正放弃IE

真正的响应式,当更改quantity or price 的时候,total自动变化。

要点:

  • get的时候进行 track
  • set的时候进行 trigger

Reflect的superPower?

let product = { 
   
        price: 5,
        quantity: 2
    }
    let proxiedProduct = new Proxy(product, { 
   
      get(target, key) { 
   
        console.log('Get was called with key = ' + key);
        return target[key]
      }
    })

此时 Reflect要来临了。

我们会传入第三个参数,receiver,并且传入的reflect中。这个receiver保证了当我们的对象有继承自其他对象的值或函数时,this指针能正确的指向使用的对象。这将避免我们在vue2中有的响应式警告。

    let product = { 
   
        price: 5,
        quantity: 2
    }
    let proxiedProduct = new Proxy(product, { 
   
        get(target, key, receiver) { 
   
            console.log</

今天的文章Vue Mastery – 响应式原理分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:http://bianchenghao.cn/63160.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注