当前位置: 首页 > Web前端 > HTML5

一起写一个即插即用的VueLoading插件

时间:2023-04-05 00:45:48 HTML5

.loading{width:50px;高度:50px;边框:4px实心rgba(0,0,0,0.1);边界半径:50%;左颜色:红色;animation:loading1sinfinitelinear;}@keyframesloading{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}无论你要实现什么样的网站,Loading状态都是必不可少的一部分,给用户一个喘息的机会,给服务器一个响应的时间。从使用方式上看,无论是从0开始写还是直接下载,都会抽象成一个组件,用的时候Loading加载,或者通过API手动显示或者隐藏...this.$wait.show()awaitfetch('http://example.org')this.$wait.hide()或者通过Loading状态在组件之间切换。如果要注册为全局状态,还需要在axios类的网络请求包中添加拦截器,然后设置一个全局的Loading状态。每次有网络请求或Loading状态设置为根据已设置的URL加载,请求完成后,Set为Done。注册axios拦截器:letloadingUrls=[`${apiUrl}/loading/`,`${apiUrl}/index/`,`${apiUrl}/comments/`,...]axios.interceptors.request.use((config)=>{leturl=config.urlif(loadingUrls.indexOf('url')!==-1){store.loading.isLoading=true}})axios.interceptors.response.use((response)=>{leturl=response.config.urlif(loadingUrls.indexOf('url')!==-1){store.loading.isLoading=false}})使用时获取各个组件下的加载状态,然后判断什么时候显示加载,什么时候显示真实组件。当当前页面下只有一个状态需要Loading时使用还好,但是如果一个页面下有很多不同的组件需要Loading,就需要根据不同的组件进行标记,以便已经加载的组件loaded不会重复进入Loading状态。。。随着业务的不断增加,重复的Loading判断就够让人很烦躁了。。。整理Loading的思想核心很简单,就是,需要在请求服务器的时候显示Loading,请求完成后再恢复。这个想法实现起来并不费力,但是use方法无法逃避上面的显式调用方式。按照思路,有地方可以设置Loading,设置全局拦截,在请求开始前设置状态为loading。设置全局拦截,请求结束后设置状态为完成。在触发请求的函数中拦截,设置为触发前加载,触发后设置为完成。判断请求后的数据是否非空,非空则设置完成。在最终能够实现的情况下,全局拦截设置,然后局部判断是最容易想到的,也是最容易实现的。为每个触发函数设置之前和之后看起来不错,但实现起来却是一场灾难。我们没有before和after两个函数钩子来告诉我们函数什么时候被调用,什么时候调用结束。自己实现它有很多陷阱。如果没有实现,就没有用,只能在原来的函数中一一写了。仅仅判断数据非常有限,而且只有一次机会。既然是即插即用的插件,就一定要简单易用。基本思路是使用全局拦截,但是本地判断和通常的略有不同,使用了数据绑定(当然也可以再次使用全局响应拦截),来实现吧~。样式Loading,一定要有个圆圈调用Loading,样式不是这个插件最重要的,这里简单易行,不粗暴的用CSS实现:....loading{width:50px;高度:50px;边框:4px实心rgba(0,0,0,0.1);边界半径:50%;左颜色:红色;animation:loading1sinfinitelinear;}@keyframesloading{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}固定大小50px对于正方形,使用边框-radius使其更圆,将边框设置为进度条底部,并将border-left-color设置为进度条。演示地址绑定数据和URL,对外提供使用接口上面思路中提到,这个插件是做全局拦截和数据绑定的:暴露一个source属性,从使用的组件中获取需要绑定的数据。公开一个urls属性以获取要从使用的组件中拦截的URL。....不用关心来源是什么类型的数据,我们只需要监控它,每次变化时将Loading状态设置为完成,后面我们会在urls上完善。设置请求拦截器拦截器中需要的操作是将请求中的每一个URL都推送到一个容器中,请求完成后删除。Vue.prototype.__loader_checks=[]Vue.prototype.$__loadingHTTP=newProxy({},{set:function(target,key,value,receiver){letoldValue=target[key]if(!oldValue){Vue.prototype.__loader_checks.forEach((func)=>{func(key,value)})}returnReflect.set(target,key,value,receiver)}})axios.interceptors.request.use(config=>{Vue.prototype.$__loadingHTTP[config.url]=configreturnconfig})axios.interceptors.response.use(response=>{deleteVue.prototype.$__loadingHTTP[response.config.url]returnresponse})挂载在vue实例,方便我们后面调用。当然也可以使用Vuex,但是这次插件需要高亮一个依赖,所以还是没有使用Vuex。直接挂载在Vue上的数据,无法通过computed或watch监控数据变化。我们使用Proxy拦截set方法,并在按下请求URL时执行某些操作。vue.prototype.__loader_checks用于存储请求URL时哪些实例化组件订阅了loading事件,这样每次按下URL时,都会通过Proxy分发给订阅的实例化Loading组件。订阅URL事件....每个都是一个全新的实例,所以直接在mounted中订阅url事件即可,只要有传入的url,在__loader_checks中发布每个订阅的对象,Loader实例收到后release,会判断该url是否对应自己注册的。如果是这样,它会将自己的状态设置回加载中。URL请求后,必然会更新数据。这时候,我们上面监控的source就会工作,load的状态会被设置回complete。使用插槽适配原始组件。写完上面,你可能会有一些疑惑。Loading时如何隐藏不该显示的部分?答案是用slot适配,....还是通过isLoading判断,如果是loading显示圆圈,否则会显示父组件传入的槽。请注意这里写的内容。Vue中有一个奇怪的BUG。

当有时,如果v-if和css选择器出现在同级label且style被scoped,那么用cssselector设置的style会丢失,如果key没有设置,.loading样式会丢失。除了设置key之外,还可以把嵌入的
设置为插件注册在。Vue中插件的注册方式有四种。这里使用mixin混合到各个instance中,使用方便,我们这里也注册了上面的axios拦截器。importaxiosimportLoaderfrom'./loader.vue'exportdefault{install(Vue,options){Vue.prototype.__loader_checks=[]Vue.prototype.$__loadingHTTP=newProxy({},{set:function(target,key,value,receiver){letoldValue=target[key]if(!oldValue){Vue.prototype.__loader_checks.forEach((func)=>{func(key,value)})}returnReflect.set(target,key,值,接收者)}})axios.interceptors.request.use(config=>{Vue.prototype.$__loadingHTTP[config.url]=configreturnconfig})axios.interceptors.response.use(response=>{deleteVue.prototype.$__loadingHTTP[response.config.url]返回响应})Vue.mixin({beforeCreate(){Vue.component('v-loader',Loader)}})}}在入口文件中使用插件importLoaderfrom'./plugins/loader/index.js'...Vue.use(Loader)...无需导入即可在任何组件中使用{{msg}}
根据绑定的数据和绑定的URL自动显示和隐藏Loading,无需手动设置是否隐藏isLoading,也无需在请求方法中调用show和hide打补丁测试地址上面其他通过绑定通过指定数据来确定是否已做出响应。如果请求的数据不会更新,也可以直接在axios的response中拦截,以订阅-发布的方式进行响应。最后咳咳,又到了颜(hou)素(yan)认(wu)真(chi)求Star的时候了,附上完整的项目地址(我不会告诉你上面测试地址里的代码也很完整,永远不会!)。