一、async 和 await
1、使用async 和 await 改造异步请求
在接触后端API以后就遇到了越来越多的异步请求,现在我们就使用async 和 await 改造异步请求。
async function是把返回内容包裹成个Promise返回Promise
await 它在async function里面才起作用,它可以放在任何异步的基于Promise的代码之前,它会暂停代码在这行上,直到Promise完成,然后返回结果值
如下,修改我们的异步请求
改为如下:
在function前加async,然后在axios前用await,此时返回的是请求回来的结果,因为我们要的是请求数据里的data,所以我们直接展开即const {data}接里面的data
有点重复,所以我们抽离出来做个函数
2、使用axios 拦截器添加loading效果
发送异步请求的时候,最好在界面给用户一个提示,告诉用户现在数据在读取中请耐心等待这样子,这就是经典的loading问题,这个loading字段显然就是一个全局状态,在各个页面都可能使用,那么提到全局状态,那么自热而然想到了这个store,那么现在我们就给store添加一个loading字段
然后我们在页面加个简单的loading效果
现在这种方法虽然看起来没有什么问题,但是我们要在每次发请求的地方多次加上这种commit信息来触发mutation的变化来修改store中数据的变化,这里仅仅是获取数据即get commit,但是我们后面还会有post的请求,甚至还有update、delete请求,那么每次请求中都要反复去comiit setLoading就比较麻烦,有没有什么地方可以优化。
axios就来帮助我们了,axios有一个关键特性叫Interceptors即拦截器,通过拦截器我们可以在全局层面拦截到在请求发送时和响应返回时的状态,然后我们可以在对应的钩子函数中进行一些逻辑的操作。
如下例子中,可以使用axios.interceptors.request就是发送请求的时候,然后use(),里面有config然后返回config,我们就是在use()中添加逻辑,我们的逻辑就是请求的时候把这个loading设置为true,返回的时候设置为false即可
如下,我们到main.ts中,这里面我们有一个axios.default配置,所以axios的配置呢我们都可以写到这里
现在我们这个loading已经可以在页面运作了,而且每次请求和开始的时候它都会被interceptors即拦截器完美的拦截,每次请求都会自动触发对应的mutation,非常的好用
二、Loader组件编码
1、基本部分
对应这个loading的图标,bootstrap已经为我们提供了现成的解决方案
我们需要一个占满屏幕的遮罩层,然后里面旋转图标,然后一行文字这样子
如下Loader.vue,App.vue
2、使用Teleport 进行改造
前面留下一个问题,就是loader组件是一个全局组件,但是它现在被包裹在app的container下面,
那么样式就可能会受到外层父组件的影响
vue3给我们提供了解决方案,这个解决方案就是Teleport即传送门,把我们要用的内容用<teleport>这个标签进行包裹,其中属性为to指向某个css的selected,如下,我们给指向id为back这么一个元素
但是这时候会报错,因为我们还需要在html中添加入id为back的div,所以如下
加入,如下
但是如果用户想使用这个组件,那么他还必须在html中加上一个这个div,就不方便,不是一个良好的组件设计,所以我们想使用另外的方法来实现对应的功能,我们需要在body中创建一个最顶层的div,我们可以在组件还没渲染即在dom之前手动创建一个div,然后把它id设置成back不就可以了吗,我们应该在setup中创建,因为这时候组件还没有挂载到dom节点上
如下
我们修改一下,让它loader2秒后再消失,如下
然后我们发现,即使loader已经消失了,但是它那个id为back的div还在,而且如果我们进入专栏详情页可以看到是又创建了一个div节点
随着页面来回跳转,这样的节点就越来越多,所以我们要解决这个问题,也就是说在组件卸载以后我们需要手动来清除这个节点,所以我们在onUnmounted中把这个节点删除即可