Vue.$nextTick你真的懂了吗?
在使用vue的时候,不知道大家有没有遇到这种情况,明明对这个数据进行更改了,但是当我获取它的时候怎么是上一次的值~~
vue的官方文档是这样说的:
可能你还没有注意到,Vue异步执行DOM更新。只要观察到数据变化,Vue将开启一个队列,并缓冲在同一事件循环中发生的所有数据改变。如果同一个watcher被多次触发,只会被推入到队列中一次。这种在缓冲时去除重复数据对于避免不必要的计算和DOM操作上非常重要。然后,在下一个的事件循环“tick”中,Vue刷新队列并执行实际 (已去重的) 工作。
白话一点就是说,Vue不可能对每一个数据变化都做一次渲染,它会把这些变化先放在一个异步的队列当中,同时它还会对这个队列里面的操作进行去重,比如你修改了这个数据三次,它只会保留最后一次。这些变化是都可以通过队列的形式保存起来,那现在的问题就来到了,那vue是在事件循环的哪个时机来对DOM进行修改呢?
我们都知道在一轮事件循环中,同步执行栈中代码执行完成之后,才会执行异步队列当中的内容,那我们获取DOM的操作是一个同步的呀!!那岂不是虽然我已经把数据改掉了,但是它的更新异步的,而我在获取的时候,它还没有来得及改,所以会出现文章开头的那个问题。就轮到Vue.$nextTick( )
出场了~
Vue.$nextTick( )
vue在调用Watcher更新视图时,并不会直接进行更新,而是把需要更新的Watcher加入到queueWatcher队列里,然后把具体的更新方法flushSchedulerQueue 传给nexTick 进行调用。
注意:nextTick 只是单纯通过Promise、setTimeout等方法模拟的异步任务。
class Watcher {// 执行更新操作update() {queueWatcher(this);}
}
const queue = [];
function queueWatcher(watcher: Watcher) {// 将当前 Watcher 添加到异步队列queue.push(watcher);//执行异步队列,并传入回调nextTick(flushSchedulerQueue);
}
// 更新视图的具体方法
function flushSchedulerQueue() {let watcher, id;// 排序,先渲染父节点,再渲染子节点,避免不必要的子节点渲染queue.sort((a, b) => a.id - b.id);// 遍历所有 Watcher 进行批量更新。for (index = 0; index < queue.length; index++) {watcher = queue[index];// 更新 DOMwatcher.run();}
}
在这个过程中, 会完善下列逻辑判断:
判断has 标识,避免在一个Queue 中添加相同的Watcher;
判断waiting 标识,让所有的Watcher 都在一个tick 内进行更新;
判断flushing 标识,处理Watcher 渲染时,可能产生的新Watcher。
也就是说,调用this.$nextTick
其实就是调用图中的nextTick
方法,在异步队列中执行回调函数。根据先进先出原则,修改Data 触发的更新异步队列会先得到执行,执行完成后就生成了新的DOM,接下来执行this.$nextTick
的回调函数时,能获取到更新后的DOM元素了。
应用场景
created生命周期中
在created()
生命周期钩子函数中,dom还没有被渲染,此时在该钩子函数中进行dom赋值数据(或者其它dom操作)时无异于徒劳。所以,此时this.$nextTick()
就会被大量使用。
<template><section><div ref="hello"><h1>Hello mimi ~</h1></div><button type="danger" @click="get">点击</button></section>
</template>
<script>export default {name:'tick',methods: {get() {}},created() {console.log('在created直接进行dom操作');console.log(this.$refs['hello']);this.$nextTick(() => {console.log('在nextTick回调中执行dom操作');console.log(this.$refs['hello']);});}}
</script>
对更改后的dom进行操作
<template><section><h1 ref="hello">{{ value }}</h1><button type="danger" @click="get">点击</button></section>
</template>
<script>export default {data() {return {value: 'Hello mimi ~'};},methods: {get() {this.value = '奔赴热爱';console.log('更改后直接获取:',this.$refs['hello'].innerText);this.$nextTick(() => {console.log('在nextTick中获取',this.$refs['hello'].innerText);});}}}
</script>
自己项目中遇到的例子
这个demo是一个订餐管理系统,该组件是评论模块。有全部,吐槽,满意三个按钮,点击哪一个,对应类型的评论会显示在下方。incrementTotal
是按钮绑定的点击事件,点击之后,页面下方评论所对应的数据发生变化,但不能立即更新的页面上,所以放入nextTick
回调中,进行滚动条的更新。
Vue.$nextTick你真的懂了吗?相关推荐
- 示波器_你真的懂示波器嘛?面试中会用到的示波器知识
示波器是电子工程师经常使用到的电子测量仪器,用途十分广泛,可将肉眼看不见的电信号变换成看得见的图像,便于人们研究各种电现象的变化过程.利用示波器能观察各种不同信号幅度随时间变化的波形曲线,还可以用它测 ...
- “三次握手,四次挥手”你真的懂吗?
来源:码农桃花源 解读:"拼多多"被薅的问题出在哪儿?损失将如何买单? 之前有推过一篇不错的干货<TCP之三次握手四次挥手>,前几天有兄弟投稿,开始还以为是同一篇,后经 ...
- 程序猿修仙之路--数据结构之你是否真的懂数组? c#socket TCP同步网络通信 用lambda表达式树替代反射 ASP.NET MVC如何做一个简单的非法登录拦截...
程序猿修仙之路--数据结构之你是否真的懂数组? 数据结构 但凡IT江湖侠士,算法与数据结构为必修之课.早有前辈已经明确指出:程序=算法+数据结构 .要想在之后的江湖历练中通关,数据结构必不可少.数据 ...
- 【转】先说IEnumerable,我们每天用的foreach你真的懂它吗?
[转]先说IEnumerable,我们每天用的foreach你真的懂它吗? 我们先思考几个问题: 为什么在foreach中不能修改item的值? 要实现foreach需要满足什么条件? 为什么Linq ...
- 【原创】“三次握手,四次挥手”你真的懂吗?
记得刚毕业找工作面试的时候,经常会被问到:你知道"3次握手,4次挥手"吗?这时候我会"胸有成竹"地"背诵"前期准备好的"答案&qu ...
- 你真的懂TensorFlow吗?Tensor是神马?为什么还会Flow?
本文的ipynb 格式见CSDN下载. 0维张量/标量 标量是一个数字 1维张量/向量 1维张量称为"向量". 2维张量 2维张量称为矩阵 3维张量 公用数据存储在张量 时间序列数 ...
- 关于Spring底层原理面试的那些问题,你是不是真的懂Spring?
转载自 关于Spring底层原理面试的那些问题,你是不是真的懂Spring? 1.什么是 Spring 框架?Spring 框架有哪些主要模块? Spring 框架是一个为 Java 应用程序的开发 ...
- 你真的懂Redis的5种基本数据结构吗?
摘要: 你真的懂Redis的5种基本数据结构吗?这些知识点或许你还需要看看. 本文分享自华为云社区<你真的懂Redis的5种基本数据结构吗?这些知识点或许你还需要看看>,作者:李子捌. 一 ...
- 你真的懂语音特征吗?
摘要:本文指在详细介绍语音转化声学特征的过程,并详细介绍不同声学特征在不同模型中的应用. 本文分享自华为云社区<你真的懂语音特征背后的原理吗?>,作者: 白马过平川 . 语音数据常被用于人 ...
最新文章
- Linux 性能监控常用命令
- Jenkins+PowerShell持续集成环境搭建(二)控制台项目
- javascript处理事件的一些兼容写法
- 阻止中文输入法输入拼音的时候触发input事件
- 最近看了两本低代码的书
- 浅析数字签名的工作原理 【小白级别的原创文章 仅供扫盲】
- linux8如何开启多个桌面,CentOS8安装GNOME3桌面并设置开机启动图形界面
- lisp语言与python_5种语言混合编程:C++、JS、python、Lisp、汇编
- iphone怎么重启_iPhone看完这个都要卡死机!这串神秘代码,是真的有毒
- 1996年考研数学一解析pdf
- 常见数学公式和符号的英文读法大全
- android手机截图功能,手机截屏怎么弄?安卓手机怎么截屏?
- 开心豆少儿英语好吗,收费怎么样,一年多少钱的学费
- 2022年强网杯rcefile wp
- JVM虚拟机相关知识
- Docker Hub镜像构建错误:returned a non-zero code: 8
- java+jsp+mysql实现学习资源推荐系统LearningResourceRS 个性化推荐系统 个性化学习网站推荐系统 协同过滤推荐算法 SSH(Spring+Struts+Hiber)开发框架
- 第十六届全国大学生智能车竞赛三个创意组别总决赛比赛成绩
- 判断给到的年份是否为闰年
- 拉拉米抢单发单源码 二开ui 带视频介绍 放量功能
热门文章
- IDEA太强悍了!Java把一个文件复制到另一个文件
- Hikvision IP camera URL
- IT男装逼利器:如何像黑客一样聊天 Mojo-Webqq
- 最诱人的家常菜谱nbsp;,终于知道吃啥了!
- Uboot1.1.16源代码完全注释笔记
- R语言删除/替换字符串中的标点符号/字母/数据的方法
- portainer(2):在raspberryPi 3b+上面安装docker 和 portainer 的 agent
- 数据质量总动员:Finding DQ 数据质量总动员
- Emacs 游戏彩蛋——游戏玩法介绍
- [Abp vNext 源码分析] - 5. DDD 的领域层支持(仓储、实体、值对象)