参考教程: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
中,用属性名(如price
或qunatity
)作为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
用于存放某个属性对应的所有依赖,当属性发生变化时,会执行依赖
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!