关于vue中nextTick更新机制的原理

首先我们清楚在vue中更新数据的话,DOM的更新是异步的

  <body>
    <div id="app">
      <span class="name">{{ name }}</span>
      <button @click="updateName">更改</button>
    </div>
  </body>
  <script src="./vue.js"></script>
  <script type="text/javascript">
    const app = new Vue({
      el: '#app',
      data: {
        name: '12'
      },
      methods: {
        updateName () {
          this.name = '14'
          console.log(document.getElementsByClassName('name')[0].innerHTML) // 12
        }
      }
    })
  </script>

当点击更新name后获取到的span标签中的值还是12,就说明DOM是异步更新的,而异步更新就是借助nextTick这个函数,而nextTick这个函数的功能其实很简单,就是把函数包装成异步任务

const p = Promise.resolve()
export function nextTick(fn?: () => void): Promise<void> {
  return fn ? p.then(fn) : p
}

当进行数据的更改时,是执行的同步代码,他会通知所有管理这个数据的DOM进行更新,但不是同步更新的,他会用一个队列来维护要更新的值并进行去重处理,比如下列代码

{{num}}
for(let i=0; i<100000; i++){
	num = i
}

每次设置值的时候,就会往队列中添加要更新的值并进行了去重处理,而且当往队列中第一次添加值的时候,其实就已经开启了更新DOM的异步任务,当所有的值设置完之后,异步任务才开始执行(涉及到主线程中的任务和异步任务的执行顺序),所以说不管num设置多少次,始终只会执行一次更新,而一般我们使用nextTick能够获取到更新后的DOM,就是因为它也是异步任务并且是在更新DOM的异步任务执行完之后再执行的所以能够获取最新的DOM

下面这种情况就可以证实

  <body>
    <div id="app">
      <span class="name">{{ name }}</span>
      <button @click="updateName">更改</button>
    </div>
  </body>
  <script src="./vue.js"></script>
  <script type="text/javascript">
    const app = new Vue({
      el: '#app',
      data: {
        name: '12'
      },
      methods: {
        updateName () {
          this.$nextTick(() => {
            console.log(document.getElementsByClassName('name')[0].innerHTML) // 12
          })
          this.name = '14'
          this.name = '15'
        }
      }
    })
  </script>

这样获取到的值就是12,因为更新DOM的异步任务要在设置值的时候才会执行,所以这时候$nextTick的异步任务就排在了更新DOM的异步任务的前面所以就会先执行

tips:每次重新设置不同值的时候都会像队列中添加值然后执行更新DOM的异步任务,但它其实有一个状态来管理是否已经开启了,所以并不会重复调用

function queueFlush() {
  // 避免重复调用flushJobs
  if (!isFlushing && !isFlushPending) {
    isFlushPending = true
    nextTick(flushJobs)
  }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值