响应式系统的核心思想
响应式系统的核心思想
响应式系统是现代前端框架的核心机制之一,它能够自动追踪数据变化并更新相关视图。Vue3的响应式系统基于Proxy实现,相比Vue2的Object.defineProperty有显著改进。
数据劫持与依赖收集
Vue3通过Proxy拦截对象操作,在getter中收集依赖,在setter中触发更新。这种机制比Vue2的递归遍历对象属性更高效。
const reactiveMap = new WeakMap()
function reactive(target) {
const proxy = new Proxy(target, {
get(target, key, receiver) {
track(target, key) // 收集依赖
return Reflect.get(target, key, receiver)
},
set(target, key, value, receiver) {
const oldValue = target[key]
const result = Reflect.set(target, key, value, receiver)
if (oldValue !== value) {
trigger(target, key) // 触发更新
}
return result
}
})
reactiveMap.set(target, proxy)
return proxy
}
依赖追踪的实现
每个响应式属性都会关联一个依赖集合(Dep),当属性被访问时,当前运行的副作用(effect)会被记录到依赖集合中。
let activeEffect = null
const targetMap = new WeakMap()
function track(target, key) {
if (!activeEffect) return
let depsMap = targetMap.get(target)
if (!depsMap) {
depsMap = new Map()
targetMap.set(target, depsMap)
}
let dep = depsMap.get(key)
if (!dep) {
dep = new Set()
depsMap.set(key, dep)
}
dep.add(activeEffect)
}
触发更新的过程
当响应式数据变化时,系统会查找对应的依赖集合,并执行其中所有的副作用函数。
function trigger(target, key) {
const depsMap = targetMap.get(target)
if (!depsMap) return
const effects = depsMap.get(key)
if (effects) {
effects.forEach(effect => effect())
}
}
副作用管理
副作用(effect)是响应式系统的核心概念,它代表一段会响应数据变化的代码。Vue3通过effect函数创建和管理副作用。
function effect(fn) {
const effectFn = () => {
cleanup(effectFn)
activeEffect = effectFn
fn()
activeEffect = null
}
effectFn.deps = []
effectFn()
}
function cleanup(effectFn) {
for (const dep of effectFn.deps) {
dep.delete(effectFn)
}
effectFn.deps.length = 0
}
响应式API的实现差异
Vue3提供了多种创建响应式数据的方式,每种方式有不同的特性和使用场景。
ref与reactive的区别
function ref(value) {
const refObj = {
get value() {
track(refObj, 'value')
return value
},
set value(newVal) {
if (newVal !== value) {
value = newVal
trigger(refObj, 'value')
}
}
}
return refObj
}
shallowReactive的实现
浅响应式对象只对顶层属性进行响应式处理:
function shallowReactive(target) {
return new Proxy(target, {
get(target, key, receiver) {
if (key === '__v_isReactive') return true
const res = Reflect.get(target, key, receiver)
track(target, key)
return res
},
// setter与reactive相同
})
}
响应式系统的优化策略
Vue3的响应式系统包含多项性能优化措施,确保在复杂场景下仍能保持高效。
依赖收集的优化
通过位运算标记依赖关系,减少不必要的依赖收集:
const enum TrackOpTypes {
GET = 'get',
HAS = 'has',
ITERATE = 'iterate'
}
const enum TriggerOpTypes {
SET = 'set',
ADD = 'add',
DELETE = 'delete',
CLEAR = 'clear'
}
批量更新机制
使用微任务队列批量处理更新,避免重复渲染:
const queue = []
let isFlushing = false
function queueJob(job) {
if (!queue.includes(job)) {
queue.push(job)
if (!isFlushing) {
isFlushing = true
Promise.resolve().then(flushJobs)
}
}
}
function flushJobs() {
try {
for (let i = 0; i < queue.length; i++) {
queue[i]()
}
} finally {
queue.length = 0
isFlushing = false
}
}
响应式系统与组件渲染
响应式数据变化最终会触发组件重新渲染,这个过程涉及虚拟DOM的比对和更新。
组件更新触发机制
function setupRenderEffect(instance, vnode, container) {
instance.update = effect(() => {
if (!instance.isMounted) {
// 首次渲染
const subTree = instance.render()
patch(null, subTree, container)
instance.isMounted = true
} else {
// 更新
const nextTree = instance.render()
const prevTree = instance.subTree
patch(prevTree, nextTree, container)
instance.subTree = nextTree
}
}, {
scheduler: queueJob
})
}
响应式系统的边界情况处理
实际应用中需要考虑各种特殊场景,确保响应式系统稳定可靠。
循环引用的处理
function reactive(target) {
if (reactiveMap.has(target)) {
return reactiveMap.get(target)
}
// ...其余Proxy创建逻辑
}
原始值的响应式转换
function toReactive(value) {
return isObject(value) ? reactive(value) : value
}
响应式系统的调试支持
开发环境下提供更详细的调试信息,帮助开发者理解响应式行为。
function track(target, key) {
if (__DEV__ && !activeEffect) {
console.warn(`属性 "${String(key)}" 被访问但没有活跃的effect`)
}
// ...正常track逻辑
}
响应式系统与TypeScript集成
Vue3的响应式系统完全使用TypeScript编写,提供了完善的类型支持。
interface ReactiveEffect<T = any> {
(): T
_isEffect: true
id: number
active: boolean
raw: () => T
deps: Array<Dep>
options: ReactiveEffectOptions
}
interface ReactiveEffectOptions {
lazy?: boolean
scheduler?: (job: ReactiveEffect) => void
onTrack?: (event: DebuggerEvent) => void
onTrigger?: (event: DebuggerEvent) => void
onStop?: () => void
}
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn
上一篇:Monorepo代码组织方式
下一篇:编译与运行时的分离设计