当前位置: 首页 > news >正文

Vue--nextTick--作用/用法/原理

原文网址:Vue--nextTick--作用/用法/原理_IT利刃出鞘的博客-CSDN博客

简介

说明

        本文介绍Vue的nextTick的作用、用法、原理。

官网网址

API — Vue.js

作用

        Vue 在修改数据后,视图(DOM)不会立刻更新,而是等同一事件循环中的所有数据变化完成之后,再统一进行视图更新。所以,在修改数据之后立马读取DOM是获取不到新数据的,获取到的是原来的DOM数据。

        使用nextTick可以获得DOM更新后的数据。在下次 DOM 更新之后Vue会回调nextTick指定的函数。可以在修改数据之后立即使用这个nextTick方法,在指定的函数里获取更新后的 DOM。

实例

1:修改数据后读取DOM

说明

        修改数据后立马读DOM是读不到的(读到的是旧数据),用nextTick才能读到。

代码

<template>
  <div class="outer">
    <div>
      这是CompA
    </div>
    <h3 ref="hello">{{ value1 }}</h3>
    <button @click="testClick()">测试一下</button>
  </div>
</template>

<script>

export default {
  name: 'CompA',
  data () {
    return {
      value1: 'aa'
    }
  },
  methods: {
    testClick () {
      this.value1 = 'bb'
      console.log('直接获取:' + this.$refs.hello.innerText)
      this.$nextTick(() => {
        console.log('nextTick获取:' + this.$refs.hello.innerText)
      })
    }
  }
}
</script>

<style scoped>
.outer {
  margin: 20px;
  border: 2px solid blue;
  padding: 20px;
}
</style>

测试

可以发现,直接读取值读到的是旧值,用nextTick获取到的是新值。

2:created获取DOM

说明

        我们知道,created被回调时,DOM还没有创建,读不到DOM,可以使用nextTick。

代码

<template>
  <div class="outer">
    <div>
      这是CompA
    </div>
    <h3 ref="hello">{{ value1 }}</h3>
  </div>
</template>

<script>

export default {
  name: 'CompA',
  data () {
    return {
      value1: 'aa'
    }
  },

  created () {
    console.log('created进入:' + this.$refs.hello)
    this.$nextTick(() => {
      console.log('created的nextTick:' + this.$refs.hello)
    })
  },
  mounted () {
    console.log('mounted进入:' + this.$refs.hello)
    this.$nextTick(() => {
      console.log('mounted的nextTick:' + this.$refs.hello)
    })
  }
}
</script>

<style scoped>
.outer {
  margin: 20px;
  border: 2px solid blue;
  padding: 20px;
}
</style>

结果

可以发现,在created中获取不到DOM,但在created里使用nextTick可以获取到。

Vue异步执行原理

  1. 所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。
  2. 异步任务有了运行结果时在"任务队列"(task queue)中放置一个事件。
  3. "执行栈"中的所有同步任务执行完毕时,系统会读取"任务队列"。对应的异步任务结束等待状态,进入执行栈,开始执行。
  4. 主线程不断重复上面的第三步。

第一个 tick(图例中第一个步骤,即'本次更新循环'):

  1. 首先修改数据,这是同步任务。同一事件循环的所有的同步任务都在主线程上执行,形成一个执行栈,此时还未涉及 DOM 。
  2. Vue 开启一个异步队列,并缓冲在此事件循环中发生的所有数据改变。如果同一个 watcher 被多次触发,只会被推入到队列中一次。

第二个 tick(图例中第二个步骤,即'下次更新循环'):

  1. 同步任务执行完毕,开始执行异步 watcher 队列的任务,更新 DOM 。Vue 在内部尝试对异步队列使用原生的 Promise.then 和 MessageChannel 方法,如果执行环境不支持,会采用 setTimeout(fn, 0) 代替。

第三个 tick(图例中第三个步骤):

  1. 此时就是文档所说的:“下次 DOM 更新循环结束之后”
  2. 此时通过 Vue.nextTick 获取到改变后的 DOM 。通过 setTimeout(fn, 0) 也可以同样获取到。

简单总结事件循环:

  1. 同步代码执行
  2. 查找异步队列,推入执行栈,执行Vue.nextTick[事件循环1]
  3. 查找异步队列,推入执行栈,执行Vue.nextTick[事件循环2]...

总之,异步是单独的一个tick,不会和同步在一个 tick 里发生,也是 DOM 不会马上改变的原因。

在一个tick中多次更新数据页面只更新一次

即使在 Vue 中多么频繁地修改数据,最后 Vue 页面只会更新一次。

例如:

  1. 数据 name 被 页面引用,name 会收集到 页面的 watcher;
  2. name 被修改时,会通知所有收集到的 watcher 进行更新(watcher.update);
  3. 如果name 一时间被修改三次时,按道理应该会通知三次 watcher 更新,那么页面会更新三次,但是最后只会更新一次。

这是因为:

  1. 当数据变化后,把 watcher.update 函数存放进 nextTick 的 回调数组中,并且会做过滤。
  2. 通过 watcher.id 来判断 回调数组 中是否已经存在这个 watcher 的更新函数,不存在,才 push。
  3. 之后 nextTick时 遍历回调数组,便会执行更新。

        所以当三次修改数据的时候,会 push 回调数组 三个 watcher.update,但是只有第一次是 push 成功的,其他的会被过滤掉,因为已经存在了。

        不管你修改多少次数据,nextTick 的回调数组中只存在唯一一个 watcher.update,从而页面只会更新一次。

相关文章:

  • 自动化测试项目学习笔记(五):Pytest结合allure生成测试报告以及重构项目
  • 计算机网络习题答案
  • js中的‘==‘和‘===‘
  • 一起来部署项目-采购一台云服务器
  • 【老生谈算法】matlab实现抽样定理算法源码——抽样定理
  • [从0开始机器学习]4.线性回归 正规方程
  • RayVentory以改进IT的分析,RayVentory原始数据之间轻松切换
  • Oracle 递归案例
  • Python编程 print输出函数
  • WordPress JSON REST API OAuth 1.0 认证获取Authorization Basic 码+Python api 创建文章(一)
  • 力扣 每日一题 1235. 规划兼职工作【难度:困难,rating: 2022】(动态规划+二分查找)
  • 数据挖掘-模型的评估(四)
  • 开源远程桌面软件_RustDesk_(可自建远程桌面服务器)
  • 【Django框架】——11 Django模型——02创建模型类
  • 【考研】暨南大学 848 操作系统简答题(2020-2022)
  • 【EOS】Cleos基础
  • 【译】React性能工程(下) -- 深入研究React性能调试
  • Bytom交易说明(账户管理模式)
  • classpath对获取配置文件的影响
  • GraphQL学习过程应该是这样的
  • HomeBrew常规使用教程
  • Java 多线程编程之:notify 和 wait 用法
  • JS题目及答案整理
  • SpiderData 2019年2月13日 DApp数据排行榜
  • v-if和v-for连用出现的问题
  • vue2.0一起在懵逼的海洋里越陷越深(四)
  • Yeoman_Bower_Grunt
  • 阿里云爬虫风险管理产品商业化,为云端流量保驾护航
  • 大型网站性能监测、分析与优化常见问题QA
  • 浮现式设计
  • 基于 Ueditor 的现代化编辑器 Neditor 1.5.4 发布
  • 买一台 iPhone X,还是创建一家未来的独角兽?
  • 听说你叫Java(二)–Servlet请求
  • 用 vue 组件自定义 v-model, 实现一个 Tab 组件。
  • 智能合约Solidity教程-事件和日志(一)
  • ​iOS实时查看App运行日志
  • ​水经微图Web1.5.0版即将上线
  • # include “ “ 和 # include < >两者的区别
  • (02)Cartographer源码无死角解析-(03) 新数据运行与地图保存、加载地图启动仅定位模式
  • (1)(1.13) SiK无线电高级配置(六)
  • (LeetCode) T14. Longest Common Prefix
  • (二)JAVA使用POI操作excel
  • (附表设计)不是我吹!超级全面的权限系统设计方案面世了
  • (附源码)spring boot北京冬奥会志愿者报名系统 毕业设计 150947
  • (附源码)spring boot校园健康监测管理系统 毕业设计 151047
  • (附源码)springboot青少年公共卫生教育平台 毕业设计 643214
  • (官网安装) 基于CentOS 7安装MangoDB和MangoDB Shell
  • (教学思路 C#之类三)方法参数类型(ref、out、parmas)
  • .net core开源商城系统源码,支持可视化布局小程序
  • .NET 中让 Task 支持带超时的异步等待
  • .Net(C#)自定义WinForm控件之小结篇
  • .NET单元测试
  • .Net的DataSet直接与SQL2005交互
  • .NET下ASPX编程的几个小问题
  • .Net下C#针对Excel开发控件汇总(ClosedXML,EPPlus,NPOI)