首页 > 其他分享 >await this.$nextTick()和this.$nextTick(callback)有什么区别?记一次bug调试

await this.$nextTick()和this.$nextTick(callback)有什么区别?记一次bug调试

时间:2023-08-18 19:23:25浏览次数:35  
标签:nextTick newVal await 小区 callback 切换 路由 页面

背景

需要实现一个需求,一个小区业务详情页面,在左侧菜单栏切换了小区后,详情页跟着切换。

这个详情页面是根据url上的/:id来确定小区id的,所以切换了小区后,应该切换路由。

于是这样实现:

watch: {
    // 监听小区号变化
    neighNo(newVal) {
      if (newVal) {
        // 切换路由
        this.$router.replace(`/base/business/${newVal}`)
      }
    }
 },

问题

但是实际运行后发现,整个页面的表格数据都变成空了。查看控制台,表格数据是正确的。但是不显示。

这个代码实际也只是重新打开了一个页面,为什么表格数据无法渲染了呢?

调试

打印数据是正确的,却没有渲染,也就是说,是Vue没有监听到数据的变化。

这个页面本来工作是正常的,只是重新打开了,为什么不正常了呢?

如果是不能监听数组和对象的改变的话,这个表格数据是直接赋值的,也就是数组的引用直接改变,那应该是可以监测到数组变化的。

于是用$set尝试去赋值,发现无效。同时发现,不光是这个表格的数组失去了响应性,整个data里的变量,都失去了响应性。

于是我在每个生命周期函数里进行了打印,也在watch里打印,发现先执行watch,然后destroyed,然后路由改变,然后created,然后是请求接口。因为小区切换时,当前路由本身会自动刷新一遍,所以destroyed、created会执行两次,顺序每次执行会略有不同。

那就很有可能是切换路由的时机不对,尝试nextTick之后再切换路由。

解决

this.$nextTick(()=>{
    this.$router.replace(`/base/business/${newVal}`)
}

无效。

尝试用setTimeout。setTimout是宏任务,那肯定比$nextTick执行的时机更晚。

setTimeout(() => {
    this.$router.replace(`/base/business/${newVal}`)
}, 0)

无效。

把delay从0改成500,有效果了。但是loading的时间略久,而且肉眼仔细观察会发现其实是先加载了原先页面然后快速地开始加载切换的页面。多切换几个小区,有概率失效。

这就有点奇怪了,连setTimeout都无法解决。setTimeout本身是不彻底的解决方案,是下策,在$nextTick无法解决时才应使用。而且,如果delay时间太长,那效果就很奇怪了。

正束手无策时,把$nextTick换了种写法,居然就可以了!

  watch: {
    async neighNo(newVal) {
      if (newVal) {
        await this.$nextTick()
        this.$router.replace(`/base/business/${newVal}`)
      }
    }
  },

卧槽,这和上面的代码不是一个意思的吗?为什么这就可以?

翻看Vue官方文档,$nextTick用法:


将回调延迟到下次 DOM 更新循环之后执行。在修改数据之后立即使用它,然后等待 DOM 更新。它跟全局方法 Vue.nextTick 一样,不同的是回调的 this 自动绑定到调用它的实例上。


区别仅仅是this的绑定不一样。

watch到neighNo的变化后,本身当前页会由于菜单栏小区切换而刷新,那么此时当前的页面实例将要销毁,而this应该绑定在了这个要销毁的实例上。然后又切换了路由,重新创建了页面实例,this在这个过程中失去了正确的上下文,从而导致data失去了响应性。

而用await的写法,this会根据语法作用域来确定绑定的上下文,每次都会绑定在对应的页面实例上,从而工作正常。

标签:nextTick,newVal,await,小区,callback,切换,路由,页面
From: https://www.cnblogs.com/-867259206/p/17640109.html

相关文章

  • 关于async 和await关键字
    首先async关键字是标记当前方法为异步方法await关键字是为了等待异步方法结果。类似于getResult等待结果。在返回异步方法执行结果之前主线程会被阻塞。两张图解释  直接await甚至不会开启新线程。 ......
  • async_await 源码分析
    async/await源码解析这篇文章主要是分析async/await这个语法糖,分析一下async和await是如何做到异步的。首先,我先抛出两个问题,各位可以先想一下。await之后的方法是何时执行,如何执行的?为什么await之后的代码会在不同的线程执行?demo要想知道async/await是怎么运......
  • 关于callback和std::bind的那些事
    前言使用callback常常需要绑定类的具体函数,哪些可以绑定哪些不能?分析callback不同与普通函数,其入参也是一个函数,具体行为由入参决定我们看这样一段代码https://godbolt.org/z/4YTKs567j#include<functional>#include<iostream>classA{public:voidprint(constint&......
  • vite打包报错:ERROR: Top-level await is not available in the configured target env
    在开发时,vita打包报错如下: 原因:ECMAScript提案Top-levelawait由MylesBorins提出,它可以让你在模块的最高层中使用await操作符。在这之前,你只能通过在async函数或asyncgenerators中使用await操作符。Top-levelawait是个新特性,打包不支持此特性。解决方案:1.......
  • ( async/await)与(try、catch)
    避免再请求中使用then回调,将请求后的代码变成同步的,可使用async搭配awaitasync:是一个异步的方法;return返回值实际是Promise对象,不会阻塞后面的函数await:同步运算符(then的语法糖),可阻塞async函数内的await下的其他逻辑,直到执行完成后,返回请求结果(如果有的话);并不会阻塞异步方法的线......
  • glDebugMessageCallback函数是什么?
    图形编程想要调试并不是一件容易的事,有的时候渲染出全黑的结果基本上只能凭经验来查错,特别是对于着色器,断点日志都是无效的,因此想办法掌握一些调试方法还是有必要的,不然找错误的源头可能真的会非常困难参考:https://blog.csdn.net/Jaihk662/article/details/108801019glDebugMess......
  • vue--day55--vue 的$nextTick以及MyItem编辑框
    1.语法this.$nextTick(回调函数)2.作用在下一次DOM更新结束后执行其指定的回调3.什么时间用当改变数据后,要基于更新后新的DOM进行某些操作时,要在nextTick所指定的回调函数中执行。1.App.vue<template><divid="root"><divclass="todo-container"><divclass="to......
  • JavaScript中的 "return await promise" 与 "return promise"
    原文地址:'returnawaitpromise'vs'returnpromise'inJavaScript原文作者:DmitriPavlutin译文出自:翻译计划当从异步功能中返回时,您可以等待该承诺得到解决,或者您可以直接返回它:returnawaitpromisereturnpromise:jsasyncfunctionfunc1(){constpromise=asyncOperat......
  • Unity 将UnityWebRequest改为async/await异步
    花了一点时间,对UnityWebRequest进行了简单封装,使用起来更方便一些,顺便实现了post接口轮询、重试的功能usingSystem;usingSystem.Collections;usingSystem.Collections.Generic;usingSystem.Runtime.CompilerServices;usingSystem.Text;usingSystem.Threading.Tasks;......
  • promise和async await的差别
    Promise是ES6引入的一种处理异步操作的机制。它可以表示一个异步操作的最终完成或失败,并在完成或失败后返回结果或错误信息。Async/await是ES8(ECMAScript2017)引入的一种基于Promise的语法糖,用于更简洁地处理异步操作。它可以让异步的代码看起来更像同步的代码,提供了更好......