本文涉及技术点:动态组件&异步组件内置组件keep-alive&transitionslotslot和v-slot实际场景多级tabs切换,tab项不是固定的,可以灵活控制tabitem内容的显示,如下图。目录结构目录结构大致是这样的:srccomponents-公共组件Tabs.vue-封装的Tabs组件EmptyView.vue-空页面组件*.vue-其他公共组件pages-容器组件Index.vue-主要处理一级标签data和对应的VersionList.vue的内容渲染主要是处理二级tab数据和对应的内容渲染视图-视图组件,不固定,需要动态引入,可以无限扩展project-exerciseIndex.vue...组件设计从页面元素的复用性角度考虑,我们将组件按类型分为公共组件、容器组件和视图组件。公共组件基于对页面元素的分析,我们可以将tab元素提取为公共组件。因为有两个地方用到tab切换,所以按需求封装。代码如下。我们封装的组件在Tags中,使用elementUI中的tabs组件(类库可以随意选择,不受工具限制)。公共组件Tags由两部分组成:tabstogglebar-togglebar数据由外部控制并通过props注入。内容显示区-内容显示区由插槽控制。slot外层之所以用keep-alive包裹,是因为实际的分布式组件内容是由动态组件控制的,起到了缓存优化的作用。一级容器组件Index容器组件分为:一级标签容器和二级标签容器,一级标签内容展示区负责渲染二级标签和内容区对应于选项卡。<--!src/pages/Index.vue-->
//importOwnViewfrom"../views/project-exercise/";VersionList中的template类似于一级容器组件,同样引入了publiccomponent标签和pass通过props给它添加标签,告诉通用组件要显示什么标签数据。接下来,二级标签对应的视图组件也由动态组件组件控制(分发传递给Tags组件中slot槽的内容)。Computed动态引入异步组件。与一级容器组件不同的是,它们传递给is属性的值不是组件名称,而是组件实例。这里渲染的view组件不是通过固定路径导入的,而是通过import动态导入的。这也是本文的重点。计算动态导入的组件。具体实现代码如下。...为什么要使用computed来动态导入组件,而不是像这样:...是重要的是要知道在exportdefault{}之外无法获取到vue实例,因此无法与外界通信。没有从外部传入的this.view变量,所以我们只能通过引入异步组件的概念来动态引入组件。首先,我们在计算属性中创建一个异步组件的实例,返回一个Promise。computed:{//返回PromiseloaderWiew(){return()=>import("../views/"+this.view+"/Index.vue");}},handlefulfilledincomponentmountmountedstage有rejected和rejected两种状态,fulfilled正常渲染,rejected渲染EmptyView组件。init(){//this.loaderWiew()是组件实例this.loaderWiew().then(()=>{//动态加载组件this.renderView=()=>this.loaderWiew();}).catch(()=>{//当组件不存在时处理this.renderView=()=>import("@/components/EmptyView.vue");});}...mounted(){this.init();}this.view的值匹配views目录下的子目录,匹配成功则导入成功。(后续开发中,视图组件可以无限扩展)然后,通过watch监听数据变化,重新初始化组件。watch:{tab(){//tab是通过props传入的,传入的值对应目录名this.view=this.tab;//这个.init();//改变时,说明二级tab切换后,重新渲染}},终于成功引入视图组件,正常渲染。导入失败,呈现EmptyView组件。最后设计了一个完整的多级标签切换组件,支持无限视图层组件扩展,可以根据需求灵活控制标签项内容的显示。getCurrentTab(name){consttabName=['project-exercise','full-cycle']returntabName.includes(name)?name:'empty-view';}点赞或关注,我们会不定期分享技术文章。