Content Table

Vue 同步初始化

有这样的一个需求,在组件的 beforeCreated 中需要先从服务器获取登录用户的信息,然后才能继续往下初始化。使用 jQuery 的同步 Ajax 可以实现这个功能,但是 jQuery 的同步 API 已经不再推荐使用 (浏览器里会有警告),而且现在 Ajax 更多推荐使用 Axios,但是它只支持异步 Ajax 请求,此外,Vue 的生命周期函数 beforeCreated, created, mounted 等函数不支持 async + await,看上去实现这个需求挺不容易的。

幸运的是,在 Vue 的路由守卫函数 beforeRouterEnter 中可以等待条件满足后才继续跳转路由进行新路由组件的渲染,使用这个特点能实现阻塞请求后再渲染组件的需求了:

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
<script>
import { LoadingBar } from 'iview';

export default {
beforeRouteEnter(to, from, next) {
LoadingBar.start(); // 加载动画

// // [1] Ajax 异步请求数据
requestUser().then((user) => {
// [2] 数据保存到 localStorage,结束加载动画
LoadingBar.finish();
localStorage.setItem('user', JSON.stringify(user));
next();
}).catch(() => {
LoadingBar.finish();
});
},
data() {
return {
user: null,
};
},
created() {
// [3] 从 localStorage 中获取数据
this.user = JSON.parse(localStorage.getItem('user'));
console.log(this.user);
}
};
</script>

提示:

  • 函数 beforeRouteEnter 中访问不到当前组件的上下文 (这时 this 为 undefined),所以获取到的数据需要先存储起来 (例如使用 localStorage, 不要使用 vuex,还是 this 的问题),然后在组件的生命周期函数如 beforeCreated 中获取
  • next(vm => {}),next 的回调函数在 created, mounted 等执行完后才执行,所以在它里面设置登录用户的数据满足不了我们的要求
  • 为了更好的用户体验,请求数据的时候显示加载进度条