对element-plus的表单封装,但是封装后发现在表单项的onchane事件中修改其他表单项的值页面没有重新渲染,必须使用nexttick才会生效,请问需要如何解决?
我希望在父组件中不使用nexttick能够修改其他表单项的值。
父组件使用
<script setup lang="ts">
import { ref, reactive, nextTick } from 'vue'
import HForm from '@/components/HForm/index.vue'
const dataFormRef = ref()
const dataForm = reactive({
select1Value: '',
select2Value: '选项2-2',
})
// 配置表单
const formOptions = reactive({
formItems: [
{
type: 'select',
label: '选项1',
span: 12,
name: 'select1Value',
required: true,
options: [
{ text: '选项1', value: '选项1' },
{ text: '选项2', value: '选项2' },
],
props: {
onChange: () => {
// nextTick(() => {
dataForm.select2Value = ''
// })
},
},
},
{
type: 'select',
label: '选项2',
span: 12,
name: 'select2Value',
required: true,
options: [
{ text: '选项2-1', value: '选项2-1' },
{ text: '选项2-2', value: '选项2-2' },
{ text: '选项2-3', value: '选项2-3' },
{ text: '选项2-4', value: '选项2-4' },
],
props: {},
},
],
})
</script>
<template>
<HForm v-model="dataForm" v-bind="formOptions" ref="dataFormRef" />
</template>
封装的表单组件
<template>
<div class="h-from-container">
<el-form
:model="dataForm"
label-width="auto"
v-bind="$attrs"
ref="formRef"
:rules="formRules"
>
<el-row :gutter="itemGutter">
<template v-for="item in formItems" :key="item.name">
<el-col :span="item.span" v-if="!item.hidden">
<el-form-item
:label="item.label"
:label-width="item.labelWidth"
:required="item.required"
:prop="item.name"
>
<template v-if="item.type === 'select'">
<el-select
v-model="dataForm[item.name]"
v-bind="item.props"
style="width: 100%"
>
<el-option
label="请选择"
value=""
v-if="item.props?.showNull"
></el-option>
<el-option
:label="item.optionsKey ? o[item.optionsKey.text] : o.text"
:value="
item.optionsKey ? o[item.optionsKey.value] : o.value
"
v-for="o in item.options"
:key="o.value"
></el-option>
</el-select>
</template>
</el-form-item>
</el-col>
</template>
</el-row>
</el-form>
</div>
</template>
<script setup lang="ts" name="HForm">
import { ref, onMounted, watch } from 'vue'
import type { FormRules } from 'element-plus'
import { type FormItemIntf } from './types'
const emits = defineEmits(['update:modelValue'])
const dataForm = ref<Record<string, any>>({})
const formRef = ref()
const props = withDefaults(
defineProps<{
modelValue: Record<string, any>
itemGutter?: number
formItems: FormItemIntf[]
}>(),
{ modelValue: () => ({}), itemGutter: 10, formItems: () => [] },
)
function initForm() {
initFormRules()
initFormData()
}
// 生成表单数据
function initFormData() {
dataForm.value = JSON.parse(JSON.stringify(props.modelValue))
}
const formRules = ref<FormRules>({})
// 生成表单验证规则
function initFormRules() {
const requiredItems = props.formItems.filter(e => e.required)
if (requiredItems && requiredItems.length) {
requiredItems.forEach(e => {
if (e.rules) formRules.value[e.name] = e.rules
else {
formRules.value[e.name] = [
{ required: true, message: `请填写${e.label}!` },
]
}
})
}
}
async function validate() {
return await formRef.value.validate()
}
function resetFields() {
formRef.value.resetFields()
}
function clearValidate() {
formRef.value.clearValidate()
}
// 监听当前表单数据变化,更新父组件的值
watch(
() => dataForm,
() => {
emits('update:modelValue', Object.assign(props.modelValue, dataForm.value))
},
{
deep: true,
},
)
// 监听父组件的值变化,更新当前表单数据
watch(
() => props.modelValue,
newval => {
dataForm.value = Object.assign(dataForm.value, newval)
},
{
deep: true,
},
)
onMounted(() => {
initForm()
})
defineExpose({
validate,
resetFields,
clearValidate,
})
</script>
<style scoped>
.h-form-container {
}
</style>