使用vue如何监听数组变化

  介绍

今天就跟大家聊聊有关使用vue如何监听数组变化,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。

我们知道通过Object.defineProperty()劫持数组为其设置getter和setter后,调用的数组的推动,拼接,流行等方法改变数组元素时并不会触发数组的setter,这就会造成使用上述方法改变数组后,页面上并不能及时体现这些变化,也就是数组数据变化不是响应式的(对上述不了解的可以参考这篇文章)。但实际用vue开发时,对于响应式数组,使用,拼接,流行等方法改变数组时,页面会及时体现这种变化,那么vue中是如何实现的呢?

通过vue源码可以看的出,vue重写了数组的推动,拼接、流行等方法。

//src/核心/观察者/array.js//获取数组的原型Array.prototype,上面有我们常用的数组方法
  const arrayProto=Array.prototype//创建一个空对象arrayMethods,并将arrayMethods的原型指向Array.prototype
  出口const arrayMethods=Object.create (arrayProto)//列出需要重写的数组方法名
  const methodsToPatch=[
  & # 39;推动# 39;
  & # 39;流行# 39;
  & # 39;转变# 39;
  & # 39;平移# 39;
  & # 39;拼接# 39;
  & # 39;排序# 39;
  & # 39;反向# 39;
  ]//遍历上述数组方法名,依次将上述重写后的数组方法添加到arrayMethods对象上
  methodsToPatch。forEach(函数(方法){//保存一份当前的方法名对应的数组原始方法
  const原始=arrayProto[方法]//将重写后的方法定义到arrayMethods对象上,函数mutator(){}就是重写后的方法
  def (arrayMethods、方法、功能mutator (args) {//调用数组原始方法,并传入参数参数,并将执行结果赋给结果
  const=原来的结果。应用(这个,args)//当数组调用重写后的方法时,这指向该数组,当该数组为响应式时,就可以获取到其__ob__属性
  const ob=this.__ob__
  让插入
  开关(方法){
  & # 39;推动# 39;:
  & # 39;平移# 39;:
  插入=参数
  打破
  & # 39;拼接# 39;:
  插入=args.slice (2)
  打破
  }
  如果(插入)ob.observeArray(插入)//将当前数组的变更通知给其订阅者
  ob.dep.notify ()//最后返回执行结果结果
  返回结果
  })
  })

从上面可以看出array.js中重写了数组的推动,流行,转变,平移,拼接,排序,反向七种方法,重写方法在实现时除了将数组方法名对应的原始方法调用一遍并将执行结果返回外,还通过执行ob.dep.notify()将当前数组的变更通知给其订阅者,这样当使用重写后方法改变数组后,数组订阅者会将这边变化更新到页面中。

重写完数组的上述7种方法外,我们还需要将这些重写的方法应用到数组上,因此在观察者构造函数中,可以看到在监听数据时会判断数据类型是否为数组。当为数组时,如果浏览器支持__proto__,则直接将当前数据的原型__proto__指向重写后的数组方法对象arrayMethods,如果浏览器不支持__proto__,则直接将arrayMethods上重写的方法直接定义到当前数据对象上;当数据类型为非数组时,继续递归执行数据的监听。

//src/核心/观察者/index.js
  出口类观察者{
  …
  构造函数(价值:有){
  这一点。值=https://www.yisu.com/zixun/value
  this.dep=new Dep ()
  这一点。vmCount=0
  def(价值、“__ob__”)
  如果(Array.isArray(值)){
  如果(hasProto) {
  arrayMethods protoAugment(价值)
  其他}{
  copyAugment(价值、arrayMethods arrayKeys)
  }
  this.observeArray(值)
  其他}{
  this.walk(值)
  }
  }
  …
  }
  src protoAugment(目标函数:对象){/* eslint-disable no-proto */目标。__proto__=src/* eslint-enable no-proto */}
  src功能copyAugment(目标:对象:对象,钥匙:数组<字符串>){
  (让我=0,l=keys.length;我 

经过上述处理后,对于数组,当我们调用其方法处理数组时会按照如下原型链来获取数组方法:

使用vue如何监听数组变化

对于响应式数组,当浏览器支持__proto__属性时,使用推等方法时先从其原型arrayMethods上寻找推动方法,也就是重写后的方法,处理之后数组的变化会通知到其订阅者,更新页面,当在arrayMethods上查询不到时会向上在Array.prototype上查询;当浏览器不支持__proto__属性时,使用推等方法时会先从数组自身上查询,如果查询不到会向上再Array.prototype上查询。

使用vue如何监听数组变化