关于vue中watch和computed的触发机制说说数组的操作对watch的影响

一、介绍

vue中的watch和computed相信大家都不陌生,项目中使用场景非常多。原理就不多说了,已经嚼烂了。

在这里说一下一个小小的点。对数组的不同操作,会影响watch的结果,有时项目里这是一个坑。

二、示例

下面这个代码,是点击之后对list进行一个赋值操作,watch一下list,


结果大家应该都知道,如下:

现在,我们换一下对list的操作方式,看看结果,这里就只放修改了的代码:

  public changeList() {
    const data = [1, 2, 3];
    data.forEach(item => {
      this.list.push(item * item);
    });
  }

大家预测一下结果?watch和computed打印了几次,值是什么?

不知道这个结果和你的预测是否一致呢?

我们来说一下为什么触发了一次watch,以及watch的新值和旧值相等。

首先,我们知道,目前的版本(2.6.11),vue是通过Object.defineProperty()方法来监听对数据的操作的,数组的话则对六个方法做了处理,所以数组的六个方法也能触发对应的get和set,这六个方法如下:

关于vue中watch和computed的触发机制说说数组的操作对watch的影响_第1张图片

同时,vue的处理是做了节流的,简单来说,就是为了避免触发重复的监听,如果我们在同一个tick内对触发了一个数据多次的set,但是vue只会触发一次watch。

看下面的例子


结果:

所以,vue其实是在一个tick结束之后,才会触发一次数据的watch(一个tick对应一次compile,在compile之前和之后对数据进行比较,如果不同则触发watch,数组经过处理,只要执行那6个方法则会触发)。

那么,这里的tick指的是什么?是指的eventLoop中的微任务,也就是Promise建立的那个微任务。

回到开始的示例,push方法会触发set,但是同一个tick内只会触发一次,在这次tick结束之后,list的值是[1,2,3],因为是同一个数组,所以watch中新值和旧值都指向了这个对象,所以结果如图。computed同理。

我们修改一下changeList看看结果


结果:

关于vue中watch和computed的触发机制说说数组的操作对watch的影响_第2张图片

所以,如果你的逻辑中会创建微任务或者宏任务,那么可能会触发一个数据的多次watch或者相关的computed.。

 

你可能感兴趣的:(vue)