Code前端首页关于Code前端联系我们

Vue 响应式原理是什么?

terry 5小时前 阅读数 7 #Vue
文章标签 响应式原理

在 Vue 开发中,响应式是一个非常重要的概念,那 Vue 响应式原理到底是什么呢?

数据劫持

Vue 主要通过 Object.defineProperty (在 Vue3 中部分场景也会使用 Proxy)来实现数据劫持,就是对对象的属性进行拦截,比如我们有一个对象 data = { name: '张三' },当我们通过 Vue 来处理这个数据时,它会把 data 对象的每个属性都转换成 getter 和 setter。

当我们读取这个属性(console.log(data.name)),就会触发 getter 方法,这时候 Vue 可以做一些依赖收集的操作,而当我们修改这个属性(data.name = '李四'),就会触发 setter 方法,Vue 就知道这个数据发生了变化,然后去通知相关的组件进行更新。

依赖收集

那什么是依赖收集呢?其实就是收集哪些地方使用了这个数据,举个例子,我们有一个组件,在这个组件的模板中使用了 data.name 来显示名字,当 Vue 对 data.name 进行数据劫持后,在组件渲染的时候,读取 data.name 就会触发 getter,这时候 Vue 就会把这个组件的渲染函数(或者说 watcher)收集起来,作为 data.name 的依赖。

这样一来,当 data.name 发生变化时(触发 setter),Vue 就可以遍历这个依赖列表,通知每一个依赖(也就是相关的组件)去更新自己的视图。

派发更新

当数据变化触发 setter 后,Vue 就会进行派发更新,它会从被修改的数据开始,沿着依赖关系去通知各个组件,比如还是上面那个例子,data.name 变化了,它的依赖列表里的组件就会收到通知。

组件收到通知后,会重新执行自己的渲染函数,生成新的虚拟 DOM,然后通过 Diff 算法(这也是 Vue 性能优化的一个重要部分)来比较新旧虚拟 DOM 的差异,最后只更新变化的部分到真实 DOM 上,这样就实现了视图的响应式更新,用户看到的界面就会随着数据的变化而自动更新。

数组的特殊处理

对于数组,Vue 也做了特殊处理,因为 Object.defineProperty 对数组的索引和 length 属性的监听不是那么方便,Vue 重写了数组的一些方法,push、pop、shift、unshift、splice、sort、reverse 等。

当我们调用这些数组方法时,Vue 就能知道数组发生了变化,然后同样去进行依赖收集和派发更新的操作,比如我们有一个数组 arr = [1, 2, 3],当我们执行 arr.push(4) 时,Vue 内部重写的 push 方法会被调用,它会先执行原生的 push 操作,然后通知相关组件数组更新了,组件就会重新渲染。

Vue3 中的改进

在 Vue3 中,除了部分场景继续使用 Object.defineProperty 外,还引入了 Proxy,Proxy 相比 Object.defineProperty 有很多优势,它可以直接监听对象,而不是对象的属性,这样对于新增属性或者删除属性的监听就更方便了。

比如在 Vue2 中,如果我们给一个响应式对象新增一个属性,这个属性默认是不会被监听的,需要我们使用 Vue.set 方法来处理,而在 Vue3 中,使用 Proxy 就可以更自然地监听这些变化,Proxy 的性能在一些场景下也更好,它的拦截操作更全面和高效。

Vue 的响应式原理就是通过数据劫持(Object.defineProperty 或 Proxy)、依赖收集和派发更新这几个核心步骤,让数据的变化能够自动反映到视图上,实现了数据和视图的双向绑定,大大提高了开发效率,让我们可以更专注于业务逻辑的编写,而不用手动去处理数据变化后的视图更新,这也是 Vue 成为一款流行前端框架的重要原因之一。

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门