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变化。"

相关推荐
志尊宝1 小时前
Vue3 零基础每日笔记(071):暗黑模式与主题切换——CSS 变量 + Element Plus 暗黑方案
前端·css·笔记·vue·html·前端开发·软件开发
刘发财1 小时前
前端如何生成10000页PDF文件?
前端·javascript·开源
A接拉起0072 小时前
2026 年 JavaScript 开发者需要了解的知识
前端·javascript·后端
用户11481867894842 小时前
面试官:大屏项目里十几个模块同时渲染上万条数据,怎么做到不卡?
前端·性能优化
前端市界2 小时前
Pro React Admin: 统一工程底座,承载多种应用...
前端·github
葡萄城技术团队2 小时前
dsh-spreadjs-editor 当前支持什么:安装前需要了解的几件事
前端
三*一2 小时前
优化修整算法
前端·javascript·算法
weifont4 小时前
自动化抓取和上架商品:能不动手,就少动手
运维·前端·自动化
米柆4 小时前
HTML5 audio /video 完整事件监听模板
前端·html·html5
IT_陈寒4 小时前
Vite热更新失效?你可能也踩了这个坑
前端·人工智能·后端