IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> vm.$nextTick -> 正文阅读

[JavaScript知识库]vm.$nextTick

前言:

深入浅出Vue的部分个人理解。

nextTick接收一个回调函数作为参数,它的作用是将回调函数延迟到下次DOM更新周期之后执行。它与全局方法Vue.nextTick一样,不同的是回调的this自动绑定到调用它的实例上。如果没有提供回调且在支持Promise的环境中,则返回一个Promise。

我们在开发项目时会遇到一种场景,当更新了状态(数据后),需要对新DOM做一些操作,但是这时我们其实获取不到更新后的DOM,因为还没有重新渲染,这个时候我们需要使用nextTick方法。

有一个问题:下次DOM更新周期之后执行,具体指什么时候呢? 要搞清楚这个问题,就要先弄明白什么是“下次DOM更新周期”。

? ? 在Vue.js中,当状态发生变化时.watcher会得到通知,然后出发虚拟DOM的渲染流程。而watcher触发渲染这个操作并不是同步的,而是异步的。Vue.js中有一个队列,每当需要渲染时,会将watcher推送到这个队列中,在下一次事件循环中再让watcher触发渲染的流程。

1.为什么vue.js使用异步更新队列

我们知道Vue.js2.0开始使用虚拟DOM进行渲染,变化侦测的通知只发送到组件,组件内用到的所有状态的变化都会通知到同一个watcher,然后虚拟DOM会对这个组件进行比对(“diff”)并更改DOM

也就是说,如果在同一轮事件循环中两个数据发送了变化,那么组件的watcher会收到两份通知,从而进行两次渲染。事实上,并不需要渲染两次,虚拟DOM会对整个组件进行渲染,所以只需要等所有状态都修改完毕后,一次性将整个组件的DOM渲染到最新即可。

2.什么是事件循环

我们都知道Javascript是一门单线程且非阻塞的脚本语言,这意味着JavaScript代码在执行的任何时候只有一个主线程来处理所有任务。

异步任务有两种类型:微任务和宏任务。不同类型的任务会被分配到不同的任务队列中去。

当执行栈中的所有任务都执行完毕后,会去检查微任务队列中是否有事件存在,如果存在,则会依次执行微任务队列中事件对应的回调,直到为空。然后去宏任务队列中取出一个事件,把对应的回调加入到当前执行栈,当执行栈中的所有任务都执行完毕后,检查微任务队列中是否有事件存在。无限重复此过程,就形成了一个无限循环,这个循环就叫事件循环。

属于微任务的事件

Promise.then

Process.nextTick

属于宏任务的事件包含

setTimeout

setInterval

3.$nextTick更新是异步的

(1)当更新了状态(数据后),需要对更新后的DOM进行一些操作,但是获取不到更新后的DOM。使用$nextTick这个api可以解决这个问题。

代码:

<template>
  <div class="">
    <h1 ref="aa">{{ number }}</h1>
    <button @click="fn">点击修改</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      number: 1,
    };
  },
  name: "",
  methods: {
    fn() {
      this.number++;
      console.log(this.$refs.aa.innerHTML);
    },
  },
};
</script>

<style scoped></style>

view:

可以观察到的是页面上显示的是2,实际获取的是1。

在使用了$nextTick之后。

代码:

<template>
  <div class="">
    <h1 ref="aa">{{ number }}</h1>
    <button @click="fn">点击修改</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      number: 1,
    };
  },

  name: "",

  methods: {
    fn() {
      this.number++;
      this.$nextTick(() => {
        console.log(this.$refs.aa);
      });
    },
  },
};
</script>

<style scoped></style>

view:

实现了同步。

4.Vue渲染是批量进行渲染的

代码:

<template>
  <div class="">
    <ul ref="aa">
      <li v-for="(itme, index) in arr" :key="index">{{ itme }}</li>
    </ul>
    <button @click="fn">点击</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      arr: [10, 20, 30, 40],
    };
  },
  name: "",
  methods: {
    fn() {
      this.arr.push(Math.random());
      this.arr.push(Math.random());
      this.arr.push(Math.random());
      this.$nextTick(() => {
        console.log(this.$refs.aa.childNodes.length);
      });
    },
  },
};
</script>

<style scoped></style>

点击按钮push进去三个随机数,并且获取到更新后的真实的长度。

view:

可以看出直接打印出渲染玩之后的长度。证明是批量渲染的。

论证了这句话:

也就是说,如果在同一轮事件循环中两个数据发送了变化,那么组件的watcher会收到两份通知,从而进行两次渲染。事实上,并不需要渲染两次,虚拟DOM会对整个组件进行渲染,所以只需要等所有状态都修改完毕后,一次性将整个组件的DOM渲染到最新即可。

5.总结

1.应用:如果更新的状态之后想要对更新后的DOM进行操作可以使用$nextTick这个api。此时的整个组件异步更新完成。

2.Vue组件的更新是异步的,是一个微任务。通过diff算法在进行比对完毕后,一次性进行渲染,而不是更新了一次状态就去通知watcher进行改变。

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-05-05 11:09:15  更:2022-05-05 11:09:36 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 22:41:31-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码