Vue-面试-响应式原理
2026年10月16日·Admin·1 次浏览
面试题:Vue2 / Vue3 响应式原理有什么区别?
常见问法
- 「Vue 如何实现双向绑定/响应式?」
- 「为什么 Vue2 无法检测对象新增属性、数组下标修改?」
- 「Vue3 为什么改用 Proxy?」
Vue2:基于 Object.defineProperty
对已有属性做 getter / setter 劫持:
- get:收集依赖(Dep ↔ Watcher,典型的发布-订阅)。
- set:派发更新,通知相关 Watcher 重新求值 / 渲染。
局限(高频考点)
- 无法监听新增/删除属性 → 需
Vue.set/this.$set。 - 数组不能直接监听索引与
length,故对「修改元素、变长」等方法做了变异方法重写(push等)或$set。 - 嵌套对象需在初始化时递归遍历定义属性,大对象有一定初始化成本。
Vue3:基于 Proxy
代理整个对象,拦截 get / set / deleteProperty / has / ownKeys 等:
- 新增、删除属性天然可追踪。
- 数组索引与长度变化可被拦截。
- 依赖收集更懒:访问到哪层才代理哪层(配合
track/trigger)。
底层使用 WeakMap → Map → Set 结构存储 target → key → effects,与 effect(effect 函数、watchEffect 等)联动。
依赖收集与触发(抽象模型)
- track(收集):在
get时,把当前正在运行的 effect 记到该target + key的依赖集合里。 - trigger(触发):在
set时,取出依赖集合里的 effect 执行(可能经过调度器批量、异步刷新)。
computed 本质是带缓存的 effect:只有依赖变了才重算。
一句话对比
| Vue2 | Vue3 | |
|---|---|---|
| API | defineProperty |
Proxy |
| 新增属性 | 需 API 辅助 | 直接响应 |
| 数组下标 | 受限 | 原生支持 |
| 兼容性 | IE9+(有限) | 无 IE,需现代浏览器 |