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

大家都知道,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)

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

 

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

前端卡卡西呀

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值