当前位置: 首页 > 科技观察

使用async-await使Vue装饰器更可用!

时间:2023-03-22 12:52:54 科技观察

以下三个装饰器都是利用async/await的特性实现的,将异步转为同步。需要装饰的方法一定要写成async/await,使用起来非常方便,而且实现完全隐藏在装饰器内部。前两个是在ts环境下类编写的vue中使用的。但是,看清逻辑后,很容易修改,在js环境下用在Vue组件上。1.在vue中添加一个变量,表示初始化完成。指完成业务相关的初始化逻辑。例如搜索功能:loading在搜索中显示,结果为空时不显示任何数据。但是第一次打开页面的时候,还没有搜索完,而是显示还没有数据,不合适。这时候就需要一个这样的变量来处理边界条件。用于ts环境下的vue。通过装饰器添加这个属性,并包装vue的created、mounted和beforeDestroy方法。当created或mounted中发送的请求完成后,将pageIsReady设置为true。使用这个装饰器的时候,在业务代码中没有任何感觉,没有任何精神负担。import{Constructor}from"vue/types/options";exporttypeWrapReadyProperty=T&{pageIsReady?:boolean}/***在@component之后使用这个装饰器,*组件将被注入属性pageIsReady,*创建时pageIsReady变为当mounted和mounted都被执行时为真,*需要mounted或created为async/await。(根据请求是通过哪种方法初始化组件)*然后就可以直接在模板中使用了。*在脚本中使用调用isPageReady.call(this)方法;*/exportdefaultfunctionPageReadyStatus(){letcreatedDone=false;letmountedDone=false;functionisCreatedMountedAllDone(){returncreatedDone&&mountedDone;}returnfunctionpageReadyEnhancement(target:T){constoldMounted=target.prototype.mounted||function(){}constoldCreated=target.prototype.created||function(){}constoldBeforeDestroy=target.prototype.beforeDestroy||function(){}target.prototype.pageIsReady=false;target.prototype.created=asyncfunction(...params:any[]){awaitoldCreated.apply(this,params);createdDone=true;this.pageIsReady=isCreatedMountedAllDone()}target.prototype.mounted=asyncfunction(...params:any[]){awaitoldMounted.apply(this,params);mountedDone=true;this.pageIsReady=isCreatedMountedAllDone()}target.prototype.beforeDestroy=asyncfunction(...params:any[]){awaitoldBeforeDestroy.apply(this,params);mountedDone=false;createdDone=false;this.pageIsReady=false;}returntarget};}exportfunctionisPageReady(this:WrapReadyProperty){returnthis.pageIsReady}2。为事件回调函数和按钮Dom添加防抖和加载样式。用于ts环境下的vue,通过decorator包装进行装饰。请求的包装方式是async/await。这样装饰器中只需要一个await就可以知道被包装的方法是否执行了。同时可以从事件对象中获取被点击的dom元素并进行修改。/**请确保包装方法的最后一个参数列表是点击事件的参数*/exportdefaultfunctionbuttonThrottle(){letpending=false;returnfunction(target:any,name:string):any{constbtnClickFunc=target[name];constnewFunc=asyncfunction(this:Vue,...params:any[]){if(pending){return;}constevent:Event=params[params.length-1];letbtn=event.targetasHTMLElementpending=true;constrecoverCursor=changeCursor(btn);try{awaitbtnClickFunc.apply(this,params);}catch(error){console.error(error);}recoverCursor();pending=false;};target[name]=newFunc;returntarget;};}functionchangeCursor(btn?:HTMLElement){if(btn==null){return()=>{};}constoldCursor=btn.style.cursor;btn.style.cursor="wait";return()=>{btn.style.cursor=oldCursor;};}用法:在点击事件函数上使用这个装饰器。装饰器会自动检测函数是否执行,并在执行过程中为按钮的Dom节点添加point:wait属性。import{Component,Vue}from"vue-property-decorator";importbuttonThrottlefrom"@/ui/view/utils/buttonThrottle";typeMember={account_no:string;name:string;warn?:string};@Component({components:{}})exportdefaultclassAddMemberInputextendsVue{@buttonThrottle()privateasyncconfirmAdd(){awaitthis.addMembers(this.getVaildMembers());}}3.挂载前显示白屏,用于js的vue中包裹vue对象.同上,通过async/await获取挂载或者创建,然后通过this指向vue的强度获取组件的根节点,然后根据需要修改,过程中显示其他内容。毕竟,你得到了Dom,你可以为所欲为。functionfirstPaintControl(vueObj){letoldMounted=vueObj.mounted||function(){};vueObj.mounted=asyncfunction(...params){this.$el.style.visibility='hidden';awaitoldMounted.apply(this,params);this.$el.style.visibility='visible';};returnvueObj;}