欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Vue到底如何实现数组响应式的

程序员文章站 2022-06-28 18:55:02
大家都知道,Vue2.0 实现数据响应式主要是依赖Object.defineproperty 这个API,可实际上defineproperty 不能监听数组变化,可是我们在vue中操作数组数据的时候,也能实现响应式更新,这是为什么呢?翻开 VUE 源码 中的src/core/observer/array.js 文件,我们能看到,因为vue 的开发者对数组改变数据的 7 个方法做了一些改动:...const arrayProto = Array.prototypeexport ......

大家都知道,Vue2.0 实现数据响应式主要是依赖 Object.defineproperty 这个API,可实际上 defineproperty 不能监听数组变化,可是我们在vue中操作数组数据的时候,也能实现响应式更新,这是为什么呢?

 

翻开  VUE 源码  中的 src/core/observer/array.js 文件,我们能看到,因为vue 的开发者对数组改变数据的 7 个方法做了一些改动:

...

const arrayProto = Array.prototype
export const arrayMethods = Object.create(arrayProto)

const methodsToPatch = [
  'push',
  'pop',
  'shift',
  'unshift',
  'splice',
  'sort',
  'reverse'
]

/**
 * Intercept mutating methods and emit events
 */
methodsToPatch.forEach(function (method) {
  // cache original method
  const original = arrayProto[method]
  def(arrayMethods, method, function mutator (...args) {
    const result = original.apply(this, args)
    const ob = this.__ob__
    let inserted
    switch (method) {
      case 'push':
      case 'unshift':
        inserted = args
        break
      case 'splice':
        inserted = args.slice(2)
        break
    }
    if (inserted) ob.observeArray(inserted)
    // notify change
    ob.dep.notify()
    return result
  })
})

接下来分步解析:

首先 取出 Array的原型prototype 存储在 arrayProto变量中,

const arrayProto = Array.prototype

然后 在这个原型基础之上create一个新的对象 arrayMethods

export const arrayMethods = Object.create(arrayProto)

 接下来遍历数组这7个方法,在这些方法原有功能的基础上,额外添加了通知 更新(ob.dep.notify())的操作

methodsToPatch.forEach(function (method) {
  // cache original method,存储原本的方法
  const original = arrayProto[method]

  // def为引入的方法,作用是通知更新
  def(arrayMethods, method, function mutator (...args) {
    ...
  })
})

先是正常调用当前方法

const result = original.apply(this, args)

最重要的是,最后 dep.notify() 通知更新

...
ob.dep.notify()
    return result

这期间,只能监听数组原有值的变化,而新增的 值 需要重新监听起来,这就需要:

    let inserted
    switch (method) {
      case 'push':
      case 'unshift':
        inserted = args
        break
      case 'splice':
        inserted = args.slice(2)
        break
    }
    
    // ob.observeArray给新增的属性添加监听依赖
    if (inserted) ob.observeArray(inserted)

至此,在数组原有方法的基础上,增加了数据监听依赖,以达到数组变化时候的 响应式更新。 

 

本文地址:https://blog.csdn.net/RedaTao/article/details/109537065

相关标签: 前端 vue vue.js