异步状态
问题:
异步状态会引入不确定性,代码执行结果的正确与否完全靠运气或者靠网速。而无法确定异步代码的执行阶段,在多个组件或代码块之间耦合情况下会出现代码执行错误情况,怎么办?
为了应对各种各样的需求,我们在写任何存在异步任务的代码时,都要提前做好流程设计,要确保代码的运行是严格符合期望的。
而大部分的需求都可以使用vue-router的这种方案解决掉,而这个方案无法解决的时候,那么就要清楚js的执行机制,那么就可以比较准确的知道什么时候执行那一块代码,具体如下:
1、首先要列出所有需要异步操作的代码
2、分析他们之间的依赖关系,以此决定请求的顺序
3、根据这个顺序,并结合Vue组件的父子关系,决定这些异步代码的存放位置
4、不断在脑海里过Vue的执行流程,不断完善代码,弥补纰漏
5、最后要确保,在nextTick、setTimeout、ajax、Promise等交织在一起的代码里,自己能预测出任意位置代码的执行时机
vue-router
在使用vue-router实现获取数据时有两种获取数据的方式。
1、导航完成之后获取:先完成导航,然后在接下来的组件生命周期钩子(created\mounted)中获取数据。在数据获取期间显示“加载中”之类的指示。
2、导航完成之前获取:导航完成前,在路由进入的路由钩子(beforeRouteEnter\beforeRouteUpdate\beforeRouteLeave)中获取数据,在数据获取成功后执行导航。
beforeRouteEnter\beforeRouteUpdate\beforeRouteLeave钩子都是即将进入的路由组件里的编写,如从A页面进入B页面,那么钩子就在B页面的编写钩子,由于执行beforeRouteEnter时组件还有初始化,所以无法使用this,beforeRouteUpdate时组件被复用时调用的,如路由的方式为\B\:id,这种路由的组件是会被复用的,所以只会触发beforeRouteUpdate,而beforeRouteLeave是当前页面在离开是调用的,如何使用它制作是否确认离开的,而他们都是要调用next(),否则都无法进入路由。
beforeRouteEnter的next方法的回调可以获取到当前组件的this,可以使用它设置data。
1 | beforeRouteEnter(to, from, next) { |
路由缓存与scrollBehavior
由于确保前进后退时回看自己之前的内容,而不是重新刷新,实现缓存功能。
有时浏览一个内容后点击了页面的内容进入了下一个页面查看,但想回到之前的页面继续看,而不是后退后等待刷新后重新查看之前浏览的内容,但这个的实现就要keep-alive与scrollBehavior结合使用,但这个方案需要了解scrollBehavior的执行阶段,而scrollBehavior函数在组件的生命周期mounted后beforeUpdate前执行,所以要在route组件参数meta里先设置是否缓存的参数,然后v-if在router-view里显示是否缓存的组件。
1 | <keep-alive> |
isKeepAlive是否缓存,先设置下一次路由到该页面后是否缓存。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39import Vue from 'vue'
import Router from 'vue-router'
import hotShow from '@/views/hotShow'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
name: 'hotShow',
component: hotShow,
meta: {
isKeepAlive: true
}
},
{
path: '/product/:id',
name: 'product',
component: () => import('@/views/detail'),
meta: {
isKeepAlive: true
}
}
],
// 设置只缓存后退,当前进或进入后不缓存
scrollBehavior(to, from, savedPosition) {
if (savedPosition || typeof savedPosition === 'undefined') { // 只处理设置了路由元信息的组件
from.meta.isKeepAlive = typeof from.meta.isKeepAlive === 'undefined' ? undefined : false
to.meta.isKeepAlive = typeof to.meta.isKeepAlive === 'undefined' ? undefined : true
if (savedPosition) {
return savedPosition;
}
} else {
from.meta.isKeepAlive = typeof from.meta.isKeepAlive === 'undefined' ? undefined : true
to.meta.isKeepAlive = typeof to.meta.isKeepAlive === 'undefined' ? undefined : false
}
}
})
测试过程问题
1 | 报错: |