vue3中使用动态组件和异步组件

起因

最近有个需求是,页面内容由后端返回可以展示哪些模块,以及这些模块的顺序,又到组件很多,所以想到了动态组件异步组件的结合使用。
当然后端返回的仅仅是这些模块的名字(即组件的名字)和顺序。

前期准备

1.将所有的组件放到view/template下面,如demo1/index.vuedemo2/index.vue这种。
2.要求后端返回的数据为demo1demo2等。

正文开始:

动态组件

动态组件平常用的比较多,这里就不详细介绍了,有一个点需要注意下:
1.动态组件的is可以是字符串,也可以是组件,但是在setup中,也就是组合式api中,类型一定要写成组件,如下:

<script setup>
import demo1 from "@/views/home/a.vue"
import demo2 from "@/views/home/b.vue"
const nowComponent = shallowRef(demo1)
//这里一定要是组件类型,不能是字符串!
//这里建议用shallowRef,因为用ref在深度监听的情况下,vue会有警告,在这里就不多介绍了
</script>
<template>
	<component :is="nowComponent"></component>
</template>

当然如果是选项式Api就不用在意了。

异步组件

正常使用异步组件的时候,会这样使用:

const ComponentName = defineAsyncComponent(() => import(path))

在页面中可以用两种使用方法:

<template>
	//1.直接使用
	<component-name /> 
	or
	<ComponentName />
	//2.通过component动态组件
	<component :is="ComponentName"></component>
</template>

按照我们的需求,根据名字加载组件,然后对defineAsyncComponent进行一个封装:

function getTemplate(path: string) {
  return defineAsyncComponent(() => import(path))
}

紧接着需要查找所有的组件,匹配后端返回的组件进行渲染。

读取组件列表


import { defineAsyncComponent } from "vue"
//获取所有的组件路径
let modules = import.meta.glob(['@/views/template/**/*.vue'])
interface ITemplate {
  name: string
  path: string
}
let templateArr:ITemplate[] = []
//重构成以组件名字和路径的数组
for(let x in modules) {
  const regex = /src\/views\/template\/(\S*)\/(\S*).vue/; // 要查找的字符串
  let arr = regex.exec(x)!
  if(arr) {
    templateArr.push({
      name: arr[1],
      // path: x 有改动
      path: modules[x]
    })
  }
}
//在上面的基础上对此方法进行改造
function getTemplate(str: string) {
  //根据名字匹配路径
  let obj = templateArr.find(item => str == item.name)!
  //这种写法打包会有问题,import里面的路径不能写成变量,可以写成字符串拼接的格式`../template/${name}/index.vue`
  // return defineAsyncComponent(() => import(obj.path))
  return defineAsyncComponent(obj.path)
}
export default getTemplate

到这里各个准备工作已经差不多了,我们准备一个数组作为后端返回的数据:

<script setup>
//引入上面封装好的异步组件方法
import getTemplate from "getTemplate.js"
const list = [
	{
		name: 'demo1',
		sortNum: 1,
	},
	{
		name: 'demo2',
		sortNum: 2,
	},
	{
		name: 'demo3',
		sortNum: 3,
	}
]
</script>
<template>
	<div>
		<component v-for="item in list" :key="item.sortNum" :is="getTemplate(item.name)"></component>
	</div>
</template>

本以为这样整个功能已经好了,在使用的过程中发现,当页面有元素发生变化的时候,如v-if等,就会导致所有的动态组件重新加载,这样肯定不行的。
最后也没找到原因,只是找到了一个解决方法,那就是将动态组件那一部分再放到一个组件中,然后主页面中加载这个组件就好了。
本期分享内容就结束了,欢迎大家指导,有更好的方案可以在评论区留言!

  • 6
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue可以使用动态组件异步组件来实现按需加载和优化性能。下面是两种方式的实现方法。 1. 动态组件 动态组件是通过使用`<component>`标签,并在`is`属性指定组件名来实现的。动态组件可以在运行时动态绑定组件,实现按需加载。 示例代码: ```html <template> <div> <button @click="toggleComponent">Toggle Component</button> <component :is="currentComponent"></component> </div> </template> <script> import ComponentA from './ComponentA.vue'; import ComponentB from './ComponentB.vue'; export default { components: { ComponentA, ComponentB, }, data() { return { currentComponent: 'ComponentA', }; }, methods: { toggleComponent() { this.currentComponent = this.currentComponent === 'ComponentA' ? 'ComponentB' : 'ComponentA'; }, }, }; </script> ``` 2. 异步组件 异步组件是通过使用`Vue.component()`方法来实现的。该方法接收一个函数作为参数,函数返回一个`Promise`对象,在`Promise`对象被解决时,将组件作为参数传递给`Vue.component()`方法。 示例代码: ```html <template> <div> <button @click="loadComponent">Load Component</button> <component v-if="currentComponent" :is="currentComponent"></component> </div> </template> <script> export default { data() { return { currentComponent: null, }; }, methods: { async loadComponent() { const { default: ComponentC } = await import('./ComponentC.vue'); this.currentComponent = ComponentC; }, }, }; </script> ``` 在上面的代码,我们使用了ES6的动态导入语法来异步加载组件。这将返回一个`Promise`对象,我们可以使用`await`关键字来等待`Promise`对象被解决。在`Promise`对象被解决时,我们将组件作为参数传递给`currentComponent`,并将其渲染到页面上。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值