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 小时前
Latent Space 访谈 TypeSafe CEO Diogo Almeida:Jev 是面向生产环境的 System One 模型而非万能 God 模型
前端
yzy851 小时前
Vue中下载或打开文件的JavaScript方法
前端·javascript·vue
用户298698530141 小时前
在 React 中用 JavaScript 将 Word 转换为文本
前端·javascript·react.js
计算机魔术师2 小时前
马斯克称 Grok 4.7 使 xAI 在智能体编码领域位列第三
前端
摸鱼仙人~2 小时前
前端秋招异步手写题系统刷题路线:从 Promise 到 Pipeline、LazyMan 与并发控制
前端
秋天的一阵风2 小时前
⚡上线 24 小时,13% 的付费团队连夜换到 Jev:它到底什么来头?
前端·人工智能·ai编程
程序员若风2 小时前
CSRF攻击原理介绍和利用-腾讯云开发者社区
前端·网络·安全·web安全·网络安全·csrf攻击·腾讯云开发者社区
风尘小子2 小时前
node.js系列:process配置
前端·node.js
恋猫de小郭2 小时前
AndroidX 新增 Security State ,支持可编程的系统安全状态查询
android·前端·flutter