Appearance
数据响应式
- 自动追踪数据与视图的依赖关系
- 在数据发生变化时智能更新相关联的视图
那是如何追踪数据依赖关系的?
在数据改变的时候,是如何更新视图的?
这就涉及到数据拦截了
在 vue2 中是使用的 Object.defineProperty
在 vue3 中是使用的 proxy
(也不太对,defineProperty 也有用到)
Object.defineProperty
Proxy
两者的区别
共同点
- 都可以拦截
读
、写
操作 - 都可以实现深度拦截,需要递归处理
不同点
- 拦截的目标和行为是不同的
- Object.defineProperty 是针对对象的特定属性进行读写操作的拦截
- Proxy 针对对象的多种操作,包括
属性读、写、删除、函数调用、原型设置
等。- 比如删除对象上的一个属性
- 给对象上增加一个不存在的属性
- 性能上的区别
- 如果需要拦截的对象属性很多,使用 Proxy 性能更好,可以一次性对整个对象处理
- 如果需要拦截的对象很少,使用 Object.defineProperty 会好点
Vue 中的响应式系统源码
RefImpl
reactive
响应式处理的关键
ref 的处理逻辑:
- 根据传入值的类型决定使用 getter/setter 还是 Proxy
- 基本类型使用 getter/setter
- 引用类型使用 Proxy
依赖收集机制:
- 对象操作只有被拦截的才会触发依赖收集
Vue3 中的响应式数据
- ref
- reactive
- props
- computed
响应式的核心机制:
- 当响应式数据发生变化时,会自动触发相关联的函数重新执行
- 依赖关系的建立需要满足:
- 函数必须在执行过程中访问响应式数据
- 响应式数据的访问必须被系统拦截和追踪
- 函数必须是被监控的函数
- 同步代码
一句话描述就是 只有被监控的函数,在同步代码运行期间,读取操作被拦截的响应式数据,才会建立依赖关系建立依赖关系后,响应式数据发生变化,对应的函数才会重新执行
函数
- effect
- watch
- watchEffect
- h
js
import { ref, watchEffect } from 'vue'
const state = ref({
a: 1
})
const k = state.value
const n = k.a
watchEffect(() => {
console.log('start')
state.value.a
})
setTimeout(() => {
state.value = { a: 1 }
}, 500)
setTimeout(() => {
k.a = 11
}, 1000)