vue2重点

Vue2响应式系统的工作原理

Vue2响应式系统的核心实现机制
Vue2的响应式系统基于数据劫持与发布-订阅模式,通过Object.defineProperty() API拦截数据访问与修改,并结合依赖收集机制实现视图自动更新。其核心目标是建立数据与视图之间的联动关系,当数据变化时触发依赖组件的重新渲染。

数据劫持:对象与数组的响应式处理

对象响应式实现
  1. 初始化监听
    Vue在初始化阶段通过observer方法遍历data对象,对每个属性调用defineReactive函数,该函数内部使用Object.defineProperty()定义属性的gettersetter

    • getter:当属性被访问时触发,用于依赖收集(将当前Watcher添加到Dep中)。
    • setter:当属性被修改时触发,用于派发更新(通知Dep中的所有Watcher执行更新)。
  2. 深度监听
    若属性值为对象,defineReactive会递归执行深度监听,直至属性为基本类型,确保嵌套对象的变化也能被捕获。

数组响应式实现

由于Object.defineProperty()无法原生监听数组元素变化,Vue2通过重写数组原型方法解决:

  • 拦截pushpopshiftunshiftsplicesortreverse共7个修改原数组的方法。
  • 重写后的方法在执行时会触发依赖更新,并通过dep.notify()通知视图刷新。

依赖收集与派发更新流程
核心角色

  • Observer:遍历数据对象,将所有属性转换为响应式。
  • Dep(依赖收集器):每个响应式属性对应一个Dep实例,维护依赖该属性的Watcher列表。
  • Watcher:观察者对象(如组件渲染Watcher、计算属性Watcher),负责接收数据变化通知并执行更新逻辑。
流程详解
  1. 依赖收集
    组件初次渲染时,模板解析过程中访问数据属性会触发getter,此时Dep.target指向当前渲染Watcher,该Watcher被添加到属性对应的Dep中。

  2. 派发更新
    当数据通过setter修改时,Dep会调用notify()方法,遍历所有关联的Watcher并执行其update()方法,最终触发组件重新渲染。

Vue2响应式系统的局限性与解决方案

局限性

问题场景 原因分析
动态新增/删除对象属性 Object.defineProperty()仅初始化时劫持已有属性,新增/删除属性无法触发setter[[4]]
直接修改数组索引或长度 重写的数组方法仅覆盖7个操作,直接修改索引(如this.arr[0] = 1)无法被监听[[4]]
深度监听性能开销 初始化时递归遍历所有嵌套对象,层级过深可能导致首屏渲染卡顿

解决方案

  • 新增/删除属性:使用Vue.set(obj, key, value)this.$set添加属性,Vue.delete(obj, key)删除属性[[4]]。
  • 数组操作:优先使用重写后的数组方法(如splice),或直接替换数组(如this.arr = [...this.arr, newItem])。
  • 性能优化:避免数据层级过深,或通过Object.freeze()冻结无需响应式的对象。

总结

Vue2通过Object.defineProperty()结合发布-订阅模式实现响应式,核心在于数据劫持、依赖收集与派发更新的联动。尽管存在对新增属性、数组索引修改等场景的支持限制,但可通过Vue.set等API规避。这一机制为Vue2的数据驱动视图提供了基础,而Vue3则通过Proxy API进一步优化了这些局限性。

当前网速较慢或者你使用的浏览器不支持博客特定功能,请尝试刷新或换用Chrome、Firefox等现代浏览器