前端在Vue3这样子写页面更快更高效
前言
在开发管理后台过程中,一定会遇到不少了增删改查页面,而这些页面的逻辑大多都是相同的,如获取列表数据,分页,筛选功能这些基本功能。而不同的是呈现出来的数据项。还有一些操作按钮。
对于刚开始只有1,2个页面的时候大多数开发者可能会直接将之前的页面代码再拷贝多一份出来,而随着项目的推进类似页面数量可能会越来越多,这直接导致项目代码耦合度越来越高。
这也是为什么在项目中一些可复用的函数或组件要抽离出来的主要原因之一
下面,我们封装一个通用的useList,适配大多数增删改查的列表页面,让你更快更高效的完成任务,准点下班
前置知识VueVueCompositionApi封装
我们需要将一些通用的参数和函数抽离出来,封装成一个通用hook,后续在其他页面复用相同功能更加简单方便。定义列表页面必不可少的分页数据exportdefaultfunctionuseList(){加载态constloadingref(false);当前页constcurPageref(1);总数量consttotalref(0);分页大小constpageSizeref(10);}如何获取列表数据
思考一番,让useList函数接收一个listRequestFn参数,用于请求列表中的数据。
定义一个list变量,用于存放网络请求回来的数据内容,由于在内部无法直接确定列表数据类型,通过泛型的方式让外部提供列表数据类型。exportdefaultfunctionuseListItemTypeextendsObject(listRequestFn:Function){忽略其他代码constlistrefItemType〔〕(〔〕);}
在useList中创建一个loadData函数,用于调用获取数据函数,该函数接收一个参数用于获取指定页数的数据(可选,默认为curPage的值)。执行流程设置加载状态调用外部传入的函数,将获取到的数据赋值到list和total中关闭加载态
这里使用了asyncawait语法,假设请求出错、解构出错情况会走catch代码块,再关闭加载态
这里需要注意,传入的listRequestFn函数接收的参数数量和类型是否正常对应上请根据实际情况进行调整exportdefaultfunctionuseListItemTypeextendsObject(listRequestFn:Function){忽略其他代码数据constlistrefItemType〔〕(〔〕);过滤数据获取列表数据constloadDataasync(pagecurPage。value){设置加载中loading。valuetrue;try{const{data,meta:{total:count},}awaitlistRequestFn(pageSize。value,page);list。valuedata;total。valuecount;}catch(error){console。log(请求出错了,error);}finally{关闭加载中loading。valuefalse;}};}
别忘了,还有切换分页要处理
使用watch函数监听数据,当curPage,pageSize的值发生改变时调用loadData函数获取新的数据。exportdefaultfunctionuseListItemTypeextendsObject(listRequestFn:Function){忽略其他代码监听分页数据改变watch(〔curPage,pageSize〕,(){loadData(curPage。value);});}
现在实现了基本的列表数据获取实现数据筛选器
在庞大的数据列表中,数据筛选是必不可少的功能
通常,我会将筛选条件字段定义在一个ref中,在请求时将ref丢到请求函数即可。
在useList函数中,第二个参数接收一个filterOption对象,对应列表中的筛选条件字段。
调整一下loadData函数,在请求函数中传入filterOption对象即可
注意,传入的listRequestFn函数接收的参数数量和类型是否正常对应上请根据实际情况进行调整exportdefaultfunctionuseListItemTypeextendsObject,FilterOptionextendsObject(listRequestFn:Function,filterOption:RefObject){constloadDataasync(pagecurPage。value){设置加载中loading。valuetrue;try{const{data,meta:{total:count},}awaitlistRequestFn(pageSize。value,page,filterOption。value);list。valuedata;total。valuecount;}catch(error){console。log(请求出错了,error);}finally{关闭加载中loading。valuefalse;}};}
注意,这里filterOption参数类型需要的是ref类型,否则会丢失响应式无法正常工作清空筛选器字段
在页面中,有一个重置的按钮,用于清空筛选条件。这个重复的动作可以交给reset函数处理。
通过使用Reflect将所有值设定为undefined,再重新请求一次数据。
什么是Reflect?看看这一篇文章Reflect映射对象exportdefaultfunctionuseListItemTypeextendsObject,FilterOptionextendsObject(listRequestFn:Function,filterOption:RefObject){constreset(){if(!filterOption。value)return;constkeysReflect。ownKeys(filterOption。value);filterOption。value{}asFilterOption;keys。forEach((key){Reflect。set(filterOption。value!,key,undefined);});loadData();};}导出功能
除了对数据的查看,有些界面还需要有导出数据功能(例如导出csv,excel文件),我们也把导出功能写到useList里
通常,导出功能是调用后端提供的导出Api获取一个文件下载地址,和loadData函数类似,从外部获取exportRequestFn函数来调用Api
在函数中,新增一个exportFile函数调用它。exportdefaultfunctionuseListItemTypeextendsObject,FilterOptionextendsObject(listRequestFn:Function,filterOption:RefObject,exportRequestFn?:Function){忽略其他代码constexportFileasync(){if(!exportRequestFn){thrownewError(当前没有提供exportRequestFn函数);}if(typeofexportRequestFn!function){thrownewError(exportRequestFn必须是一个函数);}try{const{data:{link},}awaitexportRequestFn(filterOption。value);window。open(link);}catch(error){console。log(导出失败,error);}};}
注意,传入的exportRequestFn函数接收的参数数量和类型是否正常对应上请根据实际情况进行调整优化
现在,整个useList已经满足了页面上的需求了,拥有了获取数据,筛选数据,导出数据,分页功能
还有一些细节方面,在上面所有代码中的try。。catch中的catch代码片段并没有做任何的处理,只是简单的console。log一下提供钩子
在useList新增一个Options对象参数,用于函数成功、失败时执行指定钩子函数与输出消息内容。定义Options类型exportinterfaceMessageType{GETDATAIFFAILED?:string;GETDATAIFSUCCEED?:string;EXPORTDATAIFFAILED?:string;EXPORTDATAIFSUCCEED?:string;}exportinterfaceOptionsType{requestError?:()void;requestSuccess?:()void;message:MessageType;}exportdefaultfunctionuseListItemTypeextendsObject,FilterOptionextendsObject(listRequestFn:Function,filterOption:RefObject,exportRequestFn?:Function,options?:OptionsType){。。。}设置Options默认值constDEFAULTMESSAGE{GETDATAIFFAILED:获取列表数据失败,EXPORTDATAIFFAILED:导出数据失败,};constDEFAULTOPTIONS:OptionsType{message:DEFAULTMESSAGE,};exportdefaultfunctionuseListItemTypeextendsObject,FilterOptionextendsObject(listRequestFn:Function,filterOption:RefObject,exportRequestFn?:Function,optionsDEFAULTOPTIONS){。。。}
在没有传递钩子的情况霞,推荐设置默认的失败时信息显示优化loadData,exportFile函数
基于elementui封装message方法import{ElMessage,MessageOptions}fromelementplus;exportfunctionmessage(message:string,option?:MessageOptions){ElMessage({message,。。。option});}exportfunctionwarningMessage(message:string,option?:MessageOptions){ElMessage({message,。。。option,type:warning});}exportfunctionerrorMessage(message:string,option?:MessageOptions){ElMessage({message,。。。option,type:error});}exportfunctioninfoMessage(message:string,option?:MessageOptions){ElMessage({message,。。。option,type:info});}
loadData函数constloadDataasync(pagecurPage。value){loading。valuetrue;try{const{data,meta:{total:count},}awaitlistRequestFn(pageSize。value,page,filterOption。value);list。valuedata;total。valuecount;执行成功钩子options?。message?。GETDATAIFSUCCEEDmessage(options。message。GETDATAIFSUCCEED);options?。requestSuccess?。();}catch(error){options?。message?。GETDATAIFFAILEDerrorMessage(options。message。GETDATAIFFAILED);执行失败钩子options?。requestError?。();}finally{loading。valuefalse;}};
exportFile函数constexportFileasync(){if(!exportRequestFn){thrownewError(当前没有提供exportRequestFn函数);}if(typeofexportRequestFn!function){thrownewError(exportRequestFn必须是一个函数);}try{const{data:{link},}awaitexportRequestFn(filterOption。value);window。open(link);显示信息options?。message?。EXPORTDATAIFSUCCEEDmessage(options。message。EXPORTDATAIFSUCCEED);执行成功钩子options?。exportSuccess?。();}catch(error){显示信息options?。message?。EXPORTDATAIFFAILEDerrorMessage(options。message。EXPORTDATAIFFAILED);执行失败钩子options?。exportError?。();}};useList使用方法templateelcollapseclassmb6elcollapseitemtitle筛选条件name1elformlabelpositionleftlabelwidth90px:modelfilterOptionelrow:gutter20elcol:xs24:sm12:md8:lg8:xl8elformitemlabel用户名elinputvmodelfilterOption。nameplaceholder筛选指定签名名称elformitemelcolelcol:xs24:sm12:md8:lg8:xl8elformitemlabel注册时间eldatepickervmodelfilterOption。timeRangetypedaterangeunlinkpanelsrangeseparator到startplaceholder开始时间endplaceholder结束时间formatYYYYMMDDHH:mmvalueformatYYYYMMDDHH:mmelformitemelcolelcol:xs24:sm24:md24:lg24:xl24elrowclassflexmt4elbuttontypeprimaryclickfilter筛选elbuttonelbuttontypeprimaryclickreset重置elbuttonelrowelcolelrowelformelcollapseitemelcollapseeltablevloadingloading:datalistborderstylewidth:100eltablecolumnlabel用户名minwidth110pxtemplatedefaultscope{{scope。row。name}}templateeltablecolumneltablecolumnlabel手机号码minwidth130pxtemplatedefaultscope{{scope。row。mobile未绑定手机号码}}templateeltablecolumneltablecolumnlabel邮箱地址minwidth130pxtemplatedefaultscope{{scope。row。email未绑定邮箱地址}}templateeltablecolumneltablecolumnpropcreateAtlabel注册时间minwidth220pxeltablecolumnwidth200pxfixedrightlabel操作templatedefaultscopeelbuttontypeprimarylinkclickdetail(scope。row)详情elbuttontemplateeltablecolumneltable0classflexjustifyendmt4elpaginationvmodel:currentpagecurPagevmodel:pagesizepageSizebackgroundlayoutsizes,prev,pager,next:totaltotal:pagesizes〔10,30,50〕template
本文useList的完整代码在github。comQC2168snip
如果您对该hook有更好的建议,欢迎pr或者在评论区留言哦
另外,为了在日常开发中节省找封装代码片段的时间和提高工作效率(摸时间),该仓库还存放一些第三方封装的代码片段,方便大家拿取(持续更新中)
文章来源:islandhttps:juejin。cnpost7172889961446768670
女人这样对待你,摆明是看上你了,别会错意文森屿鹿林这世间情感,最是爱情,让人难以捉摸。你喜欢她,爱上了她,但是却不知道她对你心意如何,不敢轻举妄动,将她追求。你很想知道她对你的心意,于是将她反复试探,追寻,最终发现了她对
失与得与人生成长人的生命是一条璀璨又波澜壮阔的长河,每个人都在书写着自己生命的长歌,有豪情壮志,有郁郁难平,有庸庸碌碌,亦有激流勇进。在人生成长中豪情难平碌碌无为都有着失与得的智慧。我们想成就什么
余生,找个可以随时说话的人人生最珍贵的,是有一个能随时陪你说话的人。当你苦恼郁闷,或者是开心快乐时,能够随时打开电话,交流你的喜怒哀乐,分享你的每段经历的那个人,请你一定要好好珍惜。找一个能随时说话的人,不
不以物喜不以己悲,做个阳光的强者,成功不是必然而是注定的很多时候,和别人交流需要耐心和专注,真正的友情是经住考验的。古人讲,不以物喜,不以己悲,然矣。有时候可以和别人,一直谈天说地,但是不必也不要和别人一直抱怨,抱怨的多了,也就失去了意
全国3大倒霉酒,明明酒质一流,却在货柜上积灰,网友不识货新中国成立以后了,白酒迎来了空前的繁荣,在这短短的70多年里,白酒界百花齐放。能一直位于前列的白酒是凤毛麟角,老大老二毋庸置疑是茅台和五粮液,后面跟着泸州老窖剑南春汾酒和洋河,它们
买猪肘子,要分清前肘和后肘,哪瘦肉多?哪胶质厚?区别不小俗话说秋冬进补,开春打虎,在寒冷的冬日里,能吃上几口肥而不腻,软嫩鲜香的猪肘子,肯定能给味蕾带来极大的满足。肘子是北方人授予的爱称,南方人则喜爱称其为蹄髈。肘子肉多胶质重,结缔组织
捣鼓红烧肉啦冬日生活打卡季五花肉500克植物油适量香叶23片辣椒3个冰糖10颗姜2片盐适量料酒2勺生抽2勺桂皮一小块八角1个大葱1段老抽1小勺小葱花适量第一步五花肉切大小合适的方块焯水35分钟
空气炸锅可以做什么美食?教你4种不一样的做法,方便快捷又好吃空气炸锅是一种新型的烹饪电器,利用空气油炸的原理,让食物变熟,空气炸锅中配备了热风扇,在加热的过程中,还能吹走食物中的水分,利用热空气加热,让其外表变得酥脆,达到近似油炸的效果。很
茅台镇比较好的酱香酒,这2款在当地声誉极高,贵州本地人都在喝茅台镇比较好的酱香酒,这2款在当地声誉极高,贵州本地人都在喝自从茅台爆火后,酱香型白酒在国内白酒市场的地位可谓是平步青云,从不知名的香型成为跟浓香酒清香酒并列三大香型的白酒,酱香酒
春风里不知是怎么了,近来总是无法入睡。时常在想生命的意义,感叹自己的无能。25年了我与这时间长河不过沧海一粟,可与这人生确实应是春风里,常怀念儿时,对未来又是无比期待,想要努力让生活更加
冰糖摩擦发出荧光的奥秘首先我们可以做个小实验找个透明的内部干燥(越干燥现象越明显)的矿泉水瓶,用它装上占瓶体积四分之一的大块冰糖。然后你就可以在伸手不见五指的房间内迅速摇晃塑料瓶,随后你就会发现瓶中的冰