Vue如何根据下拉选择的调度类型动态加载对应表单子组件
实现方案
直接用Vue内置的动态组件能力实现,完全不需要写大量v-if/else判断,后续扩展新调度类型也只需要加配置,改动量极小,具体步骤如下:
1. 在fullform.vue中建立类型与组件的映射关系
首先导入所有拆分好的差异化字段组件,维护一个映射对象,key和下拉选项的value一一对应,后续做组件匹配的时候直接查表就行,不需要写分支判断。
如果用的是Vue3 <script setup>语法,代码参考:
<script setup> import { ref } from 'vue' // 导入所有差异化字段组件,首屏不在乎体积可以直接静态导入 import TypeCommonFields from './typecommonfields.vue' import TypeOneFields from './typeonefields.vue' import TypeTwoFields from './typetwofields.vue' import TypeThreeFields from './typethreefields.vue' // 存当前选中的调度类型,默认对应下拉第一个选项 const currentScheduleType = ref('1') // 类型-组件映射表 const componentMap = { '1': TypeCommonFields, '2': TypeOneFields, '3': TypeTwoFields, '4': TypeThreeFields } // 接收commonform子组件抛上来的调度类型变更事件 const handleScheduleTypeChange = (val) => { currentScheduleType.value = val } </script>
如果要优化首屏加载速度,可以把静态导入替换成异步动态导入,需要用到对应组件的时候才会加载:
const componentMap = { '1': () => import('./typecommonfields.vue'), '2': () => import('./typeonefields.vue'), '3': () => import('./typetwofields.vue'), '4': () => import('./typethreefields.vue') }
2. 打通父子组件的选中值同步
因为调度类型下拉框放在commonform.vue子组件内部,你只需要在下拉框值变化时,通过自定义事件把选中值抛给父组件fullform即可:
首先修改commonform里的下拉框代码,加上值绑定和变更监听:
<cs-dashboard-select v-model="selectedType" :options="[ { value: '1', label: 'Type common'}, { value: '2', label: 'Type one'}, { value: '3', label: 'Type two'}, { value: '4', label: 'Type three'}, ]" name="schedule_type" @update:modelValue="$emit('typeChange', selectedType)" > Select type </cs-dashboard-select>
然后在fullform.vue里引用commonform组件的时候,监听这个抛出事件:
<CommonForm @type-change="handleScheduleTypeChange" />
3. 放置动态组件渲染位
在commonform组件的下方(也就是公共字段渲染完成的位置),用Vue内置的<component>标签,通过is属性绑定当前选中类型对应的组件,切换类型时Vue会自动卸载旧的差异化字段组件、挂载新的对应组件:
<template> <div class="form-container"> <!-- 公共表单组件,固定渲染三个通用字段 --> <CommonForm @type-change="handleScheduleTypeChange" /> <!-- 差异化字段动态渲染位 --> <component :is="componentMap[currentScheduleType]" /> <!-- 后面放表单提交按钮等公共内容即可 --> </div> </template>
如果需要给所有差异化组件统一传表单数据、绑定校验事件,直接在<component>标签上加对应的props和事件监听即可,不需要给每个组件单独配置:
<component :is="componentMap[currentScheduleType]" :form-data="baseFormData" @field-validate="handleSubFormValidate" />
这种实现方式的维护成本很低,后续新增调度类型的时候,只需要写好对应类型的字段组件,再往componentMap里加一条映射关系就行,不需要改动现有渲染逻辑,完全避免了多分支判断的冗余代码。
内容的提问来源于stack exchange,提问作者Arctic Fox
相关产品推荐
相关产品推荐

