推荐答案
Vue 的数据响应式原理是通过 Object.defineProperty
或 Proxy
来实现的。Vue 在初始化时会对 data 对象中的属性进行递归遍历,使用 Object.defineProperty
将这些属性转换为 getter 和 setter。当数据发生变化时,setter 会通知依赖该数据的视图进行更新。
本题详细解读
1. 数据劫持
Vue 在初始化时会对 data 对象进行递归遍历,使用 Object.defineProperty
将每个属性转换为 getter 和 setter。这样,当访问或修改这些属性时,Vue 能够捕获到这些操作。
-- -------------------- ---- ------- -------- ------------------- ---- ---- - -------------------------- ---- - ----------- ----- ------------- ----- ---- -------- ---------------- - ---------------- ------- --------- ------ ---- -- ---- -------- ---------------------- - -- ------- --- ---- ------- ---------------- ------- ------------ --- - ------- -- ------ - --- -
2. 依赖收集
Vue 在模板编译过程中会解析模板中的指令和插值表达式,生成渲染函数。在渲染函数执行时,会访问 data 中的属性,触发 getter,此时 Vue 会将当前的 Watcher 实例添加到依赖列表中。
-- -------------------- ---- ------- ----- ------- - --------------- -------- --- - ------- - --- ----------- - ------------------- ------- - --- ---------- - ----------- - ----- - ---------- - ----- ----- ----- - ------------------------- --------- ---------- - ----- ------ ------ - -------- - ----- -------- - ----------- ---------- - ----------- --------------------- ----------- ---------- - -
3. 派发更新
当 data 中的属性被修改时,会触发 setter,setter 会通知所有依赖该属性的 Watcher 实例,Watcher 实例会调用 update 方法,最终触发视图的重新渲染。
-- -------------------- ---- ------- ----- --- - ------------- - --------- - --- - ----------- - -------------------- - -------- - --------------------- -- -------------- - -
4. Vue 3 中的 Proxy
在 Vue 3 中,数据响应式系统使用了 Proxy
来代替 Object.defineProperty
。Proxy
可以监听整个对象的变化,而不需要递归遍历每个属性,性能更好。
-- -------------------- ---- ------- ----- ------- - - ----------- ---- --------- - ---------------- --------- ------ ------------------- ---- ---------- -- ----------- ---- ------ --------- - ---------------- ------- ----------- ------ ------------------- ---- ------ ---------- - -- ----- -------- - --- --------- ---------
通过以上机制,Vue 实现了数据的响应式,使得数据的变化能够自动反映到视图上。