携手Axios,驾驭加载逻辑:前端开发中轻松应对loading的终极秘籍

loading展示和取消是前端对接口时常关注的问题之一。本文将介绍如何结合axios更简洁地处理loading展示和取消的逻辑。通常情况下,loading可以分为按钮loading、局部loading和全局loading。
按钮loading:通常我们会在按钮loading的业务中使用以下方式:
或者:
上述代码中,我们需要处理loading的开始和结束状态,并且许多接口都需要编写类似的代码,显得冗琐。那么有没有更简洁的方式呢?
在Vue 3中,我们可以这样改进:
通过将loading状态传递给axios来统一处理loading。这样代码更简洁。具体实现方式如下:
在axios的拦截器中修改loading的值即可,需要注意传入一个ref类型的值。这种写法仅适用于Vue 3,对于Vue 2来说是不行的。
在Vue 2中,我们可能会考虑以下方式:
然而很遗憾,这样是无效的。原因是axios在进行深拷贝时,并没有处理RefImpl类的实例对象,因此在拦截器中的修改无效。但为什么Vue 3可以呢?因为Vue 3返回的是RefImpl类的实例对象,而axios在深拷贝时没有处理这种实例对象。因此,我们可以从这里入手改进axios的写法。代码如下:
上述代码对axios的post函数进行了二次封装。在调用接口时添加了loading,并将传入的loading对象转换成一个实例对象,在实例对象中记录传入的对象,从而实现响应式。
高阶函数版本:以上方案看起来还不够友好。如果不拘泥于在拦截器中封装,可以采用以下高阶函数方式:
以上代码只是一种思路,我们可以使用高阶函数对axios的post函数进行二次封装。对于get等函数也是类似的,这里不一一举例。
局部loading的添加有两种方式:
使用自定义指令传入true和false,但这种方式不够灵活,只能全局添加,无法在组件内的特定元素上添加loading。
在axios中封装,每次调用接口时传入需要添加loading的DOM元素,接口调用完成后删除DOM元素。
实现方法如下:
假设我们使用Vue 3和AntdV3技术栈进行封装。下面的代码使用了hooks将设置和删除loading的逻辑拆分出来。
axios代码:
hooks代码:
以上是基础逻辑,非常简单。只需在接口请求时添加loading,接口响应完成后删除loading。然而,可能会遇到多个接口同时请求或一个接口频繁请求需要覆盖相同的DOM元素的情况。这会导致添加的loading重叠显示。因此,上述代码定义了一个loadingDom对象,用于记录当前正在loading的DOM元素。如果有相同的DOM元素进来,就增加计数;完成后,计数减一。当计数为零时,删除loading。
以下是使用示例代码:
上述示例中,我们在两个DOM元素上分别绑定了ref,在组件内部通过head_dom和card_dom获取DOM元素的引用。然后,通过调用post函数传入dom选项来添加局部loading。
接下来,简单解释一下QSpin组件的代码:
以上代码对AntdV3的Spin组件进行了简单的二次封装。主要实现了局部loading覆盖传入的DOM元素的功能。
需要注意的是,一般情况下,我们使用相对定位和绝对定位的组合来实现loading效果。但是,本例中使用了transform和fixed定位的组合方式。原因是在项目中可能出现以下情况:
假设我们要给中间的div添加loading,使用相对定位和绝对定位的方式,中间div会添加position: relative属性。结果如下:
很明显,第三层div的定位根节点从第一层变成了第二层,导致样式错乱。因此,本例中使用了transform和fixed定位的组合方式,虽然这种情况仍可能出现,但几率大大降低。
全局loading:
全局loading很简单,如果已经封装好了局部loading,只需在配置项的dom中传入document.body即可。
感谢阅读本文,如果对你有帮助,请点赞和收藏👍。让我们一起在前端的道路上不断前行,共同成长!