vue 踩不完的异步之坑及解决

目录
  • 1. 任务需求分析
    • 1.1 两个页面,两个组件
    • 1.2 需求描述
  • 2. 功能是如何实现的?
    • 2.1 以前端思维消化需求
    • 2.2 代码实现 (简化版)
    • 2.3 代码翻译
  • 3. 遇到了什么问题?
  • 4. 问题是如何解决的?
    • 4.1 问题分析
    • 4.2 开始解决
    • 4.3 断点调试显神威

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()
  }
}

呵呵哒,异步的坑踩了一个又一个!

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • vue中如何进行异步请求

    目录 如何进行异步请求 一.axios实现异步请求 二.vue-resource实现异步请求(和axios步骤基本相同) vue接口异步请求 其他方法 如何进行异步请求 一.axios实现异步请求 1.项目中安装axiox npm install --save axios 2.在main.js中引入以供全局使用 import axios from 'axios' //可以给axios的ajax请求设置统一的主机和端口号 axios.defaults.baseURL = "http://157.1

  • Vue2 响应式系统之异步队列

    目录 场景 解决方案 代码实现 执行结果 总结 试想一下如果这里的 console.log 是渲染页面,那改变一次值就刷新一下页面,会造成严重的性能问题,页面也会不停的改变. 场景 import { observe } from "./reactive"; import Watcher from "./watcher"; const data = { a: 1, b: 2, c: 3, }; observe(data); const updateComponent

  • Vue异步更新机制及$nextTick原理的深入讲解

    目录 前言 Vue的异步更新 DOM更新是异步的 DOM更新还是批量的 事件循环 执行过程 源码深入 异步更新队列 nextTick $nextTick 总结 一般更新DOM是同步的 既然更新DOM是个同步的过程,那为什么Vue却需要借用$nextTick来处理呢? 为什么优先使用微任务? 总结 前言 相信很多人会好奇Vue内部的更新机制,或者平时工作中遇到的一些奇怪的问题需要使用$nextTick来解决,今天我们就来聊一聊Vue中的异步更新机制以及$nextTick原理 Vue的异步更新 可能

  • vue的状态更新方式(异步更新解决)

    目录 状态更新(异步更新解决) 解决方案 异步更新及nexttick 为什么需要异步更新 nextTick 原理 状态更新(异步更新解决) 在vue中状态更新是异步的,这一点和react中的setstate类似. 解决方案 非组件解决方案: <div id="example">{{message}}</div> var vm = new Vue({   el: '#example',   data: {     message: '123'   } }) vm.

  • vue 组件异步加载方式(按需加载)

    目录 组件异步加载(按需加载) 1.使用() => import() 2.使用resolve => require([’./_account’], resolve) 3. 使用Webpack 的内置语句:import(*) 4. require.ensure: 怎么实现组件异步加载 1.什么是异步组件 2.为什么需要异步加载组件 3.异步加载组件方法 组件异步加载(按需加载) 有时候打包出来的js文件过大,严重影响访问速度,这个时候我们就不得不考虑相关方法来提速,毕竟这可是会影响浏览量的. 如

  • vue 踩不完的异步之坑及解决

    目录 1. 任务需求分析 1.1 两个页面,两个组件 1.2 需求描述 2. 功能是如何实现的? 2.1 以前端思维消化需求 2.2 代码实现 (简化版) 2.3 代码翻译 3. 遇到了什么问题? 4. 问题是如何解决的? 4.1 问题分析 4.2 开始解决 4.3 断点调试显神威 Js 的异步确实完美地解决了单线程的问题,但是同时也会带来许多问题.而且随着用的框架越来越多,越来越复杂,定位问题的难度也随之上升. 不知为什么,总觉得Vue 的断点调试相比于不使用框架的情况下更难用,这可能也是花了

  • vue项目配置element-ui容易遇到的坑及解决

    目录 vue配置element-ui遇到的坑 步骤1.npm安装 步骤2 步骤3.测试 vue element-ui需要注意的问题 vue配置element-ui遇到的坑 注意:本文章参照element-ui官方文档,快速上手部分,的部分教程 步骤1.npm安装 npm i element-ui -S 步骤2 2-1.完整引入 在 main.js 中写入以下内容: import Vue from 'vue'; import ElementUI from 'element-ui'; import

  • vue踩坑记-在项目中安装依赖模块npm install报错

    在维护别人的项目的时候,在项目文件夹中安装npm install模块的时候,报错如下: npm ERR! path D:\ShopApp\node_modules\fsevents\node_modules\abbrev npm ERR! code ENOENT npm ERR! errno -4058 npm ERR! syscall access npm ERR! enoent ENOENT: no such file or directory, access 'D:\ShopApp\nod

  • Vue踩坑之Vue Watch方法不能监听到数组或对象值的改变详解

    目录 前言 一:利用索引直接改变arr的值 如我在button事件中写的(arr[0]=1000) 二:直接修改数组的长度 如this.arr.length=3 总结如下 前言 Vue不能监听到数组和对象值的变化其实和双向绑定的原理有关.Vue双向绑定原理是利用js中的Object.defineproperty重定义对象的GET和SET方法,而同时这种方法存在着缺陷.就是只能监听到对象内已有的值.在监听对象中属性变化的方法中中,无疑是 使用ES6的proxy更为优越. 同时我对Vue中不能监听到

  • vue踩坑记之npm install报错问题解决总结

    目录 前言 常见的有以下多种情况 总结 前言 很多时候安装npm install 的时候并不能直接将当前的node_modules直接一键安装到本地. 总是会出现各种各样的报错 常见的有以下多种情况 tip1:本地node 跟npm 版本不匹配,项目创建者当时的版本为14 ,而新开发者本地node默认为最新需要重新降低版本,使用cmd打开查看本地node和npm版本,询问一下同事的版本,直接去node官网重新 下载安装新的node安装包即可,或者如果本地有多个新老项目为了方便的管理各个node的

  • 详解从Vue.js源码看异步更新DOM策略及nextTick

    写在前面 因为对Vue.js很感兴趣,而且平时工作的技术栈也是Vue.js,这几个月花了些时间研究学习了一下Vue.js源码,并做了总结与输出. 文章的原地址:https://github.com/answershuto/learnVue. 在学习过程中,为Vue加上了中文的注释https://github.com/answershuto/learnVue/tree/master/vue-src,希望可以对其他想学习Vue源码的小伙伴有所帮助. 可能会有理解存在偏差的地方,欢迎提issue指出,

  • 基于IOS端微信分享失效的踩坑及解决方法

    最近的一个公众号是基于vue的spa应用,在接入微信分享和微信语音的时候出现了:在Android上一切正常,但是在ios端调用wx.config的时候总是失败,去翻了官方文档也并没有找到解决方案,最后在测试中发现是因为初始化的时候传入的URL的问题.具体过程如下: 微信config接口配置,官方文档如下: 所有需要使用JS-SDK的页面必须先注入配置信息,否则将无法调用(同一个url仅需调用一次,对于变化url的SPA的web app可在每次url变化时进行调用,目前Android微信客户端不支

  • vue源码之批量异步更新策略的深入解析

    vue异步更新源码中会有涉及事件循环.宏任务.微任务的概念,所以先了解一下这几个概念. 一.事件循环.宏任务.微任务 1.事件循环Event Loop:浏览器为了协调事件处理.脚本执行.网络请求和渲染等任务而定制的工作机制. 2.宏任务Task: 代表一个个离散的.独立的工作单位.浏览器完成一个宏任务,在下一个宏任务开始执行之前,会对页面重新渲染.主要包括创建文档对象.解析HTML.执行主线JS代码以及各种事件如页面加载.输入.网络事件和定时器等. 3.微任务:微任务是更小的任务,是在当前宏任务

  • vue resource post请求时遇到的坑

    使用 post 请求 // global Vue object Vue.http.get('/someUrl', [options]).then(successCallback, errorCallback); Vue.http.post('/someUrl', [body], [options]).then(successCallback, errorCallback); // in a Vue instance this.$http.get('/someUrl', [options]).th

  • vue 每次渲染完页面后div的滚动条保持在最底部的方法

    实例如下: //每次页面渲染完之后滚动条在最底部 updated:function(){ this.$nextTick(function(){ var div = document.getElementById('dialogue_box'); div.scrollTop = div.scrollHeight; }) } //第一次页面渲染完之后滚动条在最底部 methods:function(){ this.$nextTick(function(){ var div = document.ge

随机推荐