Vue3 对于响应式数据,不再像 Vue2 中那样递归对所有的子数据进行响应式定义了,而是再获取到深层数据的时候再去利用 reactive
进一步定义响应式, 这样设计的一大原因就是让业务代码可以更加高内聚低耦合,这对于大量数据的初始化场景来说收益会非常大。
ref
ref
与 reactive
两个函数都是用于监听数据修改,实现了数据绑定。 两者的区别在于 ref
是用于监听原始值的。 因为 js 原始值不能引用内存地址,就算进行了更改也没有办法追踪数据状态,因此ref可以将其包装成一个对象,这样就可以获取到这个变量的引用,监听修改。 ref
只有一个 value 属性。
通过使用 ref
监听变量修改,使用 watch
订阅通知。
reactive
有了 ref
的实现思路,实现 reactive
就很简单了。 ref
只是对原始类型进行了一次包装,而reactive
需要实现对象的遍历监听以及属性增删的监听。如果属性是对象,就返回一个 reactive 包装的对象,递归遍历。由于对象有多个属性,每个属性都有对应的订阅列表,因此容器 subMap
的数据结构为 WeakMap
effect
effect
是watcheffect和watch的统称。effect
其实就是一个依赖收集函数,在它内部访问了响应式数据,响应式数据就会把这个effect
函数作为依赖收集起来,下次响应式数据改了就触发它重新执行。一般与reactive
连着使用。
举个例子:
// 响应式数据
const data = reactive({ count: 0 })
// 依赖收集
watcheffect(() => console.log(data.count))
// 触发上面的effect重新执行
data.count ++
data是reactive创建的一个响应式数据。effect传入的函数因为内部访问到它上面的属性count
了,
所以形成了一个count -> effect
的依赖。下次count改变了,这个effect就会重新执行。
computed
computed
是Vue中的计算属性,在一个计算属性里可以完成各种复杂的逻辑,包括运算、函数调用等,只要最终返回一个结果就可以。计算属性是基于它们的响应式依赖进行缓存的。只在相关响应式依赖发生改变时它们才会重新求值。这就意味着只要 message 还没有发生改变,多次访问 reversedMessage 计算属性会立即返回之前的计算结果,而不必再次执行函数。其实computed
原理很简单生成一个effect函数,然后返回一个对象,这个对象的getter会执行对应的计算属性函数。
// 1. 响应式数据
const data = reactive({ count: 0 })
// 2. 计算属性
const plusOne = computed(() => data.count + 1)
// 3. 依赖收集
effect(() => console.log(plusOne.value))
// 4. 触发上面的effect重新执行
data.count ++
其实,computed
其实也是一个effect
,是一个双向依赖收集的运用。
暗号:我要报全栈
谢谢紫薯老师这一个月的教导,等我消化了这个课程,我就去报全栈。