vue 踩不完的异步之坑及解决
作者:scut_少东 发布时间:2024-04-28 09:30:05
Js 的异步确实完美地解决了单线程的问题,但是同时也会带来许多问题。而且随着用的框架越来越多,越来越复杂,定位问题的难度也随之上升。
不知为什么,总觉得Vue 的断点调试相比于不使用框架的情况下更难用,这可能也是花了一个小时才找到问题产生的根源的原因。废话少说,以下便是问题产生的全过程以及查找问题的流程与逻辑梳理。
1. 任务需求分析
1.1 两个页面,两个组件
任务需求涉及到两个页面和两个组件之间的恩怨纠纷,它们的关系如下:
1.2 需求描述
用户管理和权限管理是两个并列的页面。
点开用户管理,里是userTable 组件展示出的用户列表。
点开权限管理页面,然后点击页面上的组成员按钮,弹出modalUserList 弹框组件,modalUserList 中是userTable 组件展示的用户列表。
点开用户管理时展示的是所有的用户列表,点开权限管理再点击组成员时展示的是属于该组的成员列表。
2. 功能是如何实现的?
2.1 以前端思维消化需求
两个页面用到了同一个组件userTable,但是需要有不同的表现。所以我们需要一个tabletype 字段来标识当前是哪个页面引用了userTable 组件。
用户点击权限管理页面的时候,他的孙子元素userTable 需要根据用户点击的记录id 来获取该组的用户信息,中间涉及两层父子组件通信,不太方便,使用vuex 进行处理。
2.2 代码实现 (简化版)
用户管理页面引用userTable 组件的代码
<userTable
:tableType="1"
:userList="userList"></userTable>
权限管理页面引用modalUserList 组件的代码
<modalUserList
@closeModal="CloseModal"
:id="chosenGroupId"
:show="showUserList"></modalUserList>
modalUserList 组件引用userTable 组件的代码
<userTable
:tableType="2"
:userList="userList"></userTable>
权限管理页面点击组成员按钮时的代码
ShowGroupUserList (index, row) {
this.showUserList = true
// 通知孙子获取用户列表
this.SetAuthGetUserListTrue() // 通知孙子组件发送ajax 请求获取数据
this.SetAuthGroupId(row.id) // 设置authGroupId
}
userTable 组件mounted 和watch 代码
mounted () {
this.GetUserList()
// 权限管理点击按钮时才获取用户列表
// 是通过点击权限管理的组成员按钮进入的
if (this.authGetUserList) {
this.GetUserListByGroupId(this.authGroupId)
// 重新将刷新设为false
this.SetAuthGetUserListFalse()
}
}
watch: {
authGetUserList: function (newV, oldV) {
// 检查是否需要根据选择的权限组获取用户列表
if (newV) {
console.log(this.tableType)
if (this.tableType == 1) {
this.GetUserList()
} else {
this.GetUserListByGroupId(this.authGroupId)
}
// 重新将刷新设为false
this.SetAuthGetUserListFalse()
}
}
}
2.3 代码翻译
虽然贴了这么多代码,但是比较碎片化,一时半会可能不太好理清楚其中的逻辑所以这里再稍加解释,以上代码翻译成中文后大意如下:
使用tableType 来区分,如果是从用户管理页面进入的,那么userTable 组件直接使用GetUserList 方法获取所有用户列表并显示。
如果是从权限管理页面进入的,那么在用户点击组成员按钮的瞬间,权限管理页面发送通知告诉userTable 组件使用用户选择的行id 获取属于该权限组的用户列表并显示 (2.2 中最后两段代码)。
3. 遇到了什么问题?
先进用户管理页面,再进权限管理页面,点击组成员按钮有大概率会展示所有用户列表而不仅仅是该权限组用户列表
直接在权限管理页面点击组成员按钮有小概率会展示所有用户列表
4. 问题是如何解决的?
4.1 问题分析
分析一下问题的表现形式,针对问题的产生大概有以下两种猜测:
由于tableType 类型传值错误导致表格显示数据出错。
由于异步数据加载较慢,本次数据还没获取到,弹框就已经显示,显示内容是上次残留的数据,本次的数据获取到后由于某种原因没有触发页面重绘。
4.2 开始解决
查了一下代码发现tableType 传值并没有出现错误,第一条猜测不成立,那么大概率就是由于数据的异步获取导致的问题了。(虽然想不明白为什么获取到数据后没有触发页面重绘)
可能解决异步问题的一个猜想:等到数据加载完成了再显示弹框,而不是用户点击按钮的瞬间就显示(代价是爷孙组件通信),于是尝试在孙子组件加载数据完成时才通知爷爷组件显示弹框(父亲组件)。尝试失败,因为如果不先显示弹框,孙子组件就没有挂载,那就不能跟爷爷组件进行通信。
下一步,先显示父亲组件,等孙子组件获取数据成功后再显示孙子组件。设想功能成功实现,但是依然没有解决权限管理页面会显示所有用户列表的bug!
4.3 断点调试显神威
这个时候才想起来还是可以用断点调试的(使用Vue 以来基本都是用vue-dev-tools 进行调试了,刚好今天vue-dev-tools 又崩了...)。打断点一步一步走,发现在权限管理点击了组成员按钮的时候依然会在最后调用GetUserList 方法而不是GetUserListByGroupId 方法。为啥嘞?
回去看代码,2.2 中最后两段代码,mouted 中的写法,原来真的是有!问题!的!mounted 中的写法看起来是限先执行GetUserList,然后根据情况执行GetUserListByGroupId。可是由于异步的问题GetUserListByGroupId 方法获得返回值的时间不一定在GetUserList 之后,这就导致了bug 的不稳定性,有时正常,有时出问题了!
修改后的mounted 代码如下:
mounted () {
// 权限管理根据权限组id 获取用户列表
if (this.authGetUserList) {
this.GetUserListByGroupId(this.authGroupId)
// 重新将刷新设为false
this.SetAuthGetUserListFalse()
} else {
// 用户管理直接获取所有用户列表
this.GetUserList()
}
}
呵呵哒,异步的坑踩了一个又一个!
来源:https://blog.csdn.net/qq_33594380/article/details/79942128
猜你喜欢
- 用过NumPY的应该都知道,在二维数组中可以方便地使用区域切片功能,如下图:而这个功能在Python标准库的List中是不支持的,在List
- PDOStatement::setAttributePDOStatement::setAttribute — 设置一个语句属性(PHP 5
- Cookie 对象是一种以文件(Cookie文件)的形式保存在客户端硬盘的Cookies文件夹中的数据信息(Cookie数据)。Cookie
- 我们在编写软件时,一般会有版本号以及生成的时间,Go编译的程序中,如何添加当时的编译时间以及版本信息?C/C++语言,非常方便,可以直接使用
- 一、实现过程本文对经典手写数字数据集进行多分类,损失函数采用交叉熵,激活函数采用ReLU,优化器采用带有动量的mini-batchSGD算法
- 前言Tkinter(即 tk interface) 是 Python 标准 GUI 库,简称 “Tk&rdquo
- 目录一、使用方法二、输出结果1.id2.select_type3.table4.partitions5.type6.possible_key
- 如果你需要一个PDF文件合并工具,那么本文章完全可以满足您的要求。哈喽,大家好呀,这里是滑稽研究所。不多废话,本期我们利用Python合
- 设法让用户happy吧~只要你的设计让用户乐了,产品的个性就得到了一次彰显,而用户对网站的情感就会获得一次升华,看看下面的知名网站的人性化设
- 虽然我们一直使用书籍搜索的示例表单,并将起改进的很完美,但是这还是相当的简陋: 只包含一个字段,q。这简单的例子,我们不需要使用Django
- 数据库中有一字段type_code,有中文类型和中文类型编码,现在对type_code字段的数据进行统计处理,编码对应的字典如下:{'
- Pygame是跨平台Python模块,专为电子游戏设计,包含图像、声音。建立在SDL基础上,允许实时电子游戏研发而无需被低级语言(如机器语言
- 1.直方图的概念图像直方图是反映一个图像像素分布的统计表,其实横坐标代表了图像像素的种类,可以是灰度的,也可以是彩色的。纵坐标代表了每一种颜
- Doing INTERSECT and MINUS in MySQL Doing an INTERSECT An INTERSECT is
- property属性一种用起来像是使用实例属性一样的特殊属性,可以对应于某个方法既要保护类的封装特性,又要让开发者可以使用 对象.属性 的方
- 因为工作的原因,开发过一个拆分字符串的SQL函数,现在把它贴出来,与大家共勉学习。该函数如下: &
- zipfilePython 中 zipfile 模块提供了对 zip 压缩文件的一系列操作。f=zipfile.ZipFile(&
- 前言很多时候开发者需要删除文件。可能是他错误地创建了文件,或者不再需要该文件。无论出于何种原因,都有一些方法可以通过Python来删除文件,
- Web 标准要求一览表Russ WeakleyJjgod Jiang14-Aug-2004目录1 Web 标准,不仅仅是“不用表格的站点”2
- 最近学到了一个有趣的装饰器写法,就记录一下。装饰器是一个返回函数的函数。写一个装饰器,除了最常见的在函数中定义函数以外,Python还允许使