响应式
渲染函数也是函数
一处数据发生变化,与他相关的内容会同步发生变化。
响应式的基本思路:
要跟踪数据的变化,当数据变化时,更新相关(依赖)的运算。
为了能够更新相关运算(运算的代码需要被重复执行),应将其置于函数中方便调用
这个函数 通常被称为 effect 副作用函数
依赖关系的收集 track
变化通知依赖
Vue 的响应式
Vue 通过 effect 来跟踪当前正在运行的函数.
effect 是一个函数的包裹器,在函数被调用之前就启动跟踪
Vue 知道哪个 effect 在何时运行,并能在需要时再次执行它。
data 返回的对象 将被包裹在响应式代理中(同一个对象返回相同的代理),将计算函数包裹在一个 effect 中。render 函数 与 computed 类似,也是被包裹在一个 effect 中
从 Vue 3 开始,响应性以独立包存在。如 ref、reactive 等允许我们在不使用组件的情况下,将一个对象包裹在一个响应式代理中。
vue2 响应式实现
通过 Object.defineProperty 劫持 getter setter,对于新增的属性 单独进行 $set 进行劫持。
数组则重写了其原型的方法。对于元素的修改不做响应式(性能考虑)
vue3
基于 Proxy 代理
响应式API
reactive 相当于 Vue 2.x 中的 Vue.observable()。
ref 创建独立的响应式值(原始值) 通过 value 属性访问其值。
ref 自动解包的情况 (不需要.value 就可以直接获得值):
- 模板中访问(前提是它被注册了,不然模板中也访问不了)
- 当 ref 作为响应式对象的直接属性(不能被array,map包裹)被访问或更改
特殊:如果用新的 ref 赋值对象下原先的 ref,ref会被替换,而不是 ref 套 ref 的存在,这时可以理解成没有解包.
使用
readonly
防止更改响应式对象const copy = readonly(original); // copy 可以访问但不能修改
effect
清除 effect 中的异步 effect
需要清除的场景:
- effect 即将重新执行时
- 侦听器被停止
方法:传入一个函数(onInvalidate)去注册失效回调
effect 的刷新时机:
- 初始化的时候的立即执行
- 当数据发生改变时,会在 更新前 执行 (默认)
若要在更新后执行,需要在 watchEffect 时传入参数
{flush: 'post'}
track
trigger
触发就是依次调用依赖的副作用函数 effect