本篇文章主要以理解Vue3
动态组件,及其相关应用与问题解析。
什么是 Vue3 动态组件?
简单来说,这里的动态,即:能够根据组件的呈现条件,来调整好自己需要呈现的组件,以此来满足对需求的实现。
注:和动态样式一样,通过用户的操作来确定是什么类型的组件。
基本使用
在 Vue3 中,使用动态组件非常简单,我们只需要在模板中使用<component>
标签,并通过设置组件的is
属性来指定要渲染的组件。例如:
javaScript
<component :is="currentComponent"></component>
其中,currentComponent
是一个变量,它的值可以是以下 2 种:
- 已注册的组件名,或 HTML 标签名称
- 导入的组件对象
以下是示例:
javaScript
<script>
import { Transition, TransitionGroup } from 'vue'
export default {
components: {
Transition,
TransitionGroup
}
}
</script>
<template>
<component :is="isGroup ? 'TransitionGroup' : 'Transition'">
...
</component>
</template>
在这个例子中,我们可以看到,component
所呈现的组件,是由isGroup
来决定的。
注意:
如果将组件本身传递给 is 而不是其名称,则不需要注册,例如在 <script setup>
中。
如果在 <component>
标签上使用 v-model
,模板编译器会将其扩展为 modelValue prop
和 update:modelValue
事件监听器,就像对任何其他组件一样。但是,这与原生 HTML 元素不兼容,例如 <input>
或 <select>
。因此,在动态创建的原生元素上使用 v-model
将不起作用:
javaScript
<script setup>
import { ref } from 'vue'
const tag = ref('input')
const username = ref('')
</script>
<template>
<!-- 由于 'input' 是原生 HTML 元素,因此这个 v-model 不起作用 -->
<component :is="tag" v-model="username" />
</template>
应用场景
灵活运用 Vue3
的动态组件功能,能够帮助我们满足动态性和灵活性的需求:
- 条件渲染
这也是上面所说的,根据组件呈现的条件来呈现不同的组件。如:根据用户权限加载权限组件或根据用户选择加载不同的组件(可移动看上面的示例!!)
- 动态表单
根据表单类型及步骤,动态地渲染表单,以免加载整个表单,比如在我们进行登录的时候,会遇到诸如验证码的东西,有时候产品的需求可能需要我们在不同情况下换验证码的方式:可能有滑块、填数字等。
- 复用和扩展组件
利用动态化的呈现,能够在一定程度下,减少对组件的重复利用,这样也便于争取内存和空间。
- 配置组件的选择
在一些低代码平台中,通过对组件进行动态化处理,我们能够根据用户配置选择和加载特定组件,快速生成定制化应用程序
- 路由视图切换
在路由器中使用动态组件实现动态路由视图切换,根据路由路径加载相应组件,实现无缝页面切换
示例
- 通过组件名来动态更新组件 - (动态更新)
我们可以看以下的示例,我们通过两个按钮来改变currentPage
的值,以此来改变component
中的:is
的值,来改变该组件。
javaScript
<script setup lang="ts">
import { ref } from "vue";
const currentPage = ref<string>("demo-company");
//定义一个方法来对组件名进行修改
const changePage = (page: string) => {
currentPage.value = page;
};
</script>
<template>
<h3><a @click.stop="changePage('demo-company')">Company</a></h3>
<h3><a @click.stop="changePage('demo-personal')">Personal</a></h3>
<div style="border: 1px solid #000">
<h2>Content:</h2>
<component :is="currentPage"></component>
</div>
</template>
当然,我们也是能够将组件名对象存入一个模块中,进而我们去接收其参数,来实现组件的动态渲染,如以下例子:
javaScript
<template>
<component :is="item.component" v-for="item in globalComponents" :key="item.key" :ref="(vnode:any)=>item.vnode = vnode" v-bind="item.props"></component>
</template>
<script setup lang="ts">
//获取该元素状态
import { useGlobalStore } from '@/store';
const { globalComponents } = toRefs(useGlobalStore());
</script>
- 动态组件间的通信
动态组件的传值,除了支持v-bind
传值以外,还支持ref
引用传值。使用引用传值的时候,需要注意的是:需要确定组件之后,再使用ref
属性进行传值,否则将会无法获取应用组件的属性。
javaScript
<template>
<keep-alive>
<component :is="componentName"></component>
</keep-alive>
</template>
<script setup lang="ts">
import { ref } from "vue";
const componentName = ref("ComponentA");
</script>
- 组件销毁与缓存
当我们在切换组件的时候,在组件切换之后,会导致原组件销毁,导致之前的数据丢失。这个时候,如果我们能够在组件切换的过程中能够保持组件的状态的话,避免一些重复渲染而导致的性能问题,则我们能够在动态组件上使用keep-alive
来缓存组件中的数据。
javaScript
template>
<keep-alive>
<component :is="componentName"></component>
</keep-alive>
</template>
<script setup lang="ts">
import { ref } from "vue";
const componentName = ref("ComponentA");
</script>
总结
动态组件是 Vue 中非常重要的一个组件类型,我们能够通过去使用它,来实现更为复杂的切换组件逻辑。当然,使用该组件类型,笔者认为还是需要学会去搭配不同的类型及方法,已达到更好的性能优化、简洁代码的目的。
笔者能力精力有限,如有错误,还望大家及时指出改进!