Proxy 响应式原理

Vue3用Proxy重写了响应式系统(Vue2用的是Object.defineProperty),这是一个高频面试题。

核心原理

Proxy是ES6提供的原生API,可以"拦截"对一个对象的各种操作(读取属性、修改属性、删除属性等),Vue3的响应式,本质上就是用Proxy包一层你的数据对象,当你读取/修改属性时,Vue能感知到,从而触发相应的更新。

简化版的核心逻辑长这样:

javascript

function reactive(target) {

return new Proxy(target, {

// 读取属性时触发

get(obj, key) {

track(obj, key); // "追踪依赖":记录"这个属性被谁用了"(比如被某个组件的渲染函数用了)

return objkey;

},

// 修改属性时触发

set(obj, key, value) {

objkey = value;

trigger(obj, key); // "触发更新":通知所有依赖这个属性的地方,"我变了,你们该更新了"

return true;

}

});

}

具体到实际使用:

javascript

const state = reactive({ count: 0 });

// 模板里用到了 state.count,相当于触发了 get,Vue记录下"这个视图依赖state.count"

console.log(state.count);

state.count++; // 触发了 set,Vue知道count变了,去通知所有依赖它的视图,触发重新渲染

为什么Vue3要从Object.defineProperty换成Proxy------这是最常见的追问

Vue2的Object.defineProperty有几个明显缺陷:

只能拦截"已经存在"的属性,如果你后来给对象新增一个属性,Vue2是感知不到的(这就是Vue2里为什么要用Vue.set()这种特殊API才能让新增属性变成响应式)

对数组的支持很差------defineProperty拦截不了数组的索引赋值(arr0 = xxx)和长度变化,Vue2要单独重写数组的push、pop等方法才能让这些操作触发响应式

需要递归遍历对象的每一个属性,提前用defineProperty一个个包裹,性能开销大,而且深层嵌套对象需要递归处理

Proxy的优势:

可以拦截整个对象,不管是已有属性还是新增属性,统一都能被拦截到,不需要Vue.set这种特殊API

对数组天然支持,索引赋值、length变化都能被正确拦截

可以做到懒递归(访问到深层属性时才递归处理,而不是一开始就全部遍历包裹),性能更好

总结:

"Vue3用Proxy重写响应式,核心是用Proxy包裹数据对象,拦截get和set操作,get的时候收集依赖(记录这个数据被哪些地方用到),set的时候触发更新(通知所有依赖它的地方重新渲染)。相比Vue2用的Object.defineProperty,Proxy能直接监听到属性的新增和删除,不需要Vue.set这种特殊API,对数组的支持也更好,因为defineProperty拦截不了数组索引赋值和length变化。"

相关推荐
jktantan3 小时前
Vue keep-alive 切标签后滚动位置回顶?因为 onDeactivated 里读到的 scrollTop 是 0
前端·javascript·vue.js
2601_962885724 小时前
quotes 字段全解:涨跌幅、振幅、换手率的口径与单位
java·前端·spring
excel4 小时前
encodeURI 和 encodeURIComponent 有什么区别?
前端
前端精髓4 小时前
调用openrouter的免费API模型
java·前端·javascript
赛博守夜人5 小时前
AI安全攻防与治理之十四:AI 安全测试不能脱离传统安全,Web、API、移动端与模型攻击面的组合拳
前端·人工智能·安全
开开心心_Every5 小时前
快速隐藏程序工具自定义快捷键一键切换
java·开发语言·前端·spring·智能手机·word·intellij-idea
networknomad5 小时前
OpenReplay:自己搭的会话回放工具,给前端排错用的
前端·其他
缓慢更新6 小时前
AI 辅助生成单测:从接口定义到用例的流水线
java·服务器·前端·网络·数据库·人工智能
陈随易6 小时前
AI 运维服务器,安全又可靠的方法
前端·后端·程序员
风骏时光牛马7 小时前
AI稳定性治理体系构建与疑难问题深度分析
前端