原因是这样的,因为项目中需要频繁的使用 form 表单,劳动力感觉非常重复,就决定还是对 element-plus 的 form 组件进行二次封装,尽量的做到配置化的开发。其中在开发 select 的 remote 模式的时候遇到了一些问题,自己调试了很久也没有找到解决办法。代码如下:
代码块 1 为二次封装的组件。核心思路就是根据 formItem 中的 type 字段,渲染不同类型的表单组件。
// 仅展示有问题的核心逻辑
<template>
<el-form class="table-search-form"
:model="props.model"
:rules="props.rules">
<el-row :gutter="32">
<el-col
v-for="(formItem, index) in props.formItems"
:key="index"
:span="formItem.span ? formItem.span : 6">
<el-form-item
:label="formItem.label"
:prop="formItem.prop">
<-- 隐藏其他类型 -->
<el-select
v-if="formItem.type === FORM_ITEM_TYPES.REMOTE_SELECT"
v-model="props.model[formItem.prop]"
:placeholder="formItem.placeholder ? formItem.placeholder : formItem.label"
clearable
filterable
remote
:remote-method="formItem.remoteMethod"
style="width: 100%;">
<el-option
v-for="(option, index) in formItem.options"
:key="index"
:label="option.label"
:value="option.value"/>
</el-select>
</el-form-item>
</el-col>
</el-row>
</el-form>
</template>
<script lang="ts" setup>
import {defineProps} from 'vue'
enum FORM_ITEM_TYPES {
INPUT = 'input',
SELECT = 'select',
REMOTE_SELECT = 'remoteSelect'
}
const props = defineProps({
formItems: {
type: Array,
default: () => []
},
model: {
type: Object,
default: () => ({})
},
rules: {
type: Object,
default: () => ({})
}
})
</script>
代码块 2 为使用模块。
<template>
<table-search-form
:form-items="formItems"
:model="model"
:rules="rules"/>
</template>
<script lang="ts" setup>
import {reactive, ref} from 'vue'
import TableSearchForm from '@/components/TableSearchForm/index.vue'
const roles = ref<any[]>([
{label: 'Role 1', value: 1}
])
const handleRemoteMethod = (query: string) => {
setTimeout(() => {
roles.value = [
{label: 'Role 2', value: 2},
{label: 'Role 3', value: 3}
]
// 打印点 1
console.log(roles.value)
}, 1000)
}
const formItems = [
// ...省略
{
label: '角色 ID',
prop: 'roleId',
type: 'remoteSelect',
remoteMethod: handleRemoteMethod,
options: roles.value
}
]
const model = reactive({
username: '张三',
gender: 0,
roleId: ''
})
const rules = {
username: [{required: true, message: '用户名未输入。', trigger: 'none'}]
}
</script>
因为是 remote 模式的 select ,所以我会传入一个 handleRemoteMethod 函数,动态修改它的 options ,这里的 options 用了一个 ref 进行接受然后传递到组件内部。但是当我发现触发 handleRemoteMethod 之后,打印出来的值(即:打印点 1 )已经修改了,但是组件渲染依旧只有 “Role 1” 这 1 个选项。但是我使用 roles.value.push(...[]) 的方法,可以正常的改变其渲染。 请问各位大佬,这是为啥?我应该如何做,求答疑解惑。
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.