项目场景:

项目当中用了 vben 框架, vben 是基于 ant design 封装的,项目中有个需求是一个筛选表单,其中筛选条件中通过下拉列表来完成,两个筛选下拉列表有着联动关系

上图是期望的实现结果,客户和工地有着层级关系,当客户切换,对应工地列表会重新加载,而且选中状态清空,其他的选项不变

问题描述

这里在写的时候,一开始的思路是在所属客户的选中事件中清空工地这个字段的值 但是 vue3 + ts 是真的真的不熟悉啊啊啊啊

总之来看看代码叭

//过滤表单相关的代码

const searchSchemas: FormSchema[] = [

{

field: 'state',

component: 'Select',

label: '设备状态',

colProps: { span: 4 },

componentProps: {

allowClear: true,

dictType: 'bu_device_status',

},

},

{

field: 'name',

component: 'Input',

colProps: { span: 4 },

label: '设备名称',

componentProps: {

allowClear: true,

},

},

{

field: 'number',

component: 'Input',

colProps: { span: 4 },

label: '设备编号',

componentProps: {

allowClear: true,

},

},

{

field: 'customerId',

component: 'Select',

label: '设备所属客户',

colProps: { span: 4 },

componentProps: {

allowClear: true,

onChange: handleCustomerChange, // 这里是自己定义了一个函数,当客户状态改变后执行的

options: customerOptions, // customerOptions 是在某个方法中获取到了客户列表的数据

},

},

{

field: 'siteId',

component: 'Select',

label: '设备所属工地',

colProps: { span: 4 },

componentProps: {

allowClear: true,

options: siteOptions,

}

}

];

下面这里是清空工地下拉列表的相关代码, updateSite 是在 handleCustomerChange 函数中执行的函数 但是这里发现另一个问题 : 用 setFieldsValue 只设置 siteId 这一个字段为空的时候,整个表单全都被清空了 解决方案,在需要设置 siteId 为空之前,先将所有字段当前的值全部都取出来,然后在设置 siteId 的时候再将所有的数据全部再赋值给对应的字段

// 这里定义一个 formRef 对象,是响应式的 ,然后表单对象当中用 ref 来绑定上

const formRef = ref();

// 以下注释掉的全部都是错误的写法,同样踩雷的可以避一避哈哈哈

const updateSite = (customerId: string, siteOptionsArr: Array) => {

console.log('try to clear site');

// console.log(searchSchemas)

// this.$refs[siteIdRef].resetFields(); // 找不到 refs 啥的

// searchSchemas.resetFields() //resetFields 不是个函数啥的

// this.props.form.resetFields();

// siteIdRef.current?.resetFields();

console.log(formRef.value);

// formRef.value.setFieldsValue({})

const searchObj = ref(formRef.value.getFieldsValue()); // 这里是获取当前过滤表单中的所有字段的值

// console.log(searchObj.value.state)

// console.log(searchObj.value.name)

// console.log(searchObj.value.number)

// 将 siteId 字段的值设置为 " " ,但是这里把其他的字段都取出来又再设置回去的原因是 : 发现当只设置 siteId 这一个字段为空的时候,整个表单全都被清空了

formRef.value.setFieldsValue({state:searchObj.value.state,name:searchObj.value.name,number:searchObj.value.number,siteId: ''})

// setTimeout(() => {

// form.setFieldsValue({

// personName: obj.personName,

// })

// }, 0)

// formRef.value.setFieldsValue(siteId, '')

// formRef.value.resetFields('siteId');

// resetSite();

// formRef.current?.resetFields();

// searchSchemas.setFieldsValue({username: n})

// setFieldsValue

// valiDate.siteId = ''

// siteIdRef.value.resetFields()

console.log('真的重置了吗');

siteOptionsArr.length = 0;

ConstructionSitList({

organizationId: customerId,

}).then((res) => {

console.log('res', res);

res.list.forEach((element) => {

siteOptionsArr.push({ value: element.organizationId, label: element.name });

});

});

console.log(siteOptionsArr);

// return s/

};

下面这张图就是一次次试代码 , 就当看看笑话吧 ,哈哈哈 真的是语法都不知道,全靠蒙

原因分析:

主要有点坑的是 setFieldsValue 来设置某个字段的时候其他的字段会被清空

更加优化一点的方案

在上面的解决思路中,假设表单中有 n 个字段,只有一个需要清空,通过 getFieldsValue 取出来之后,一个个放到 setFieldsValue 中的,但是如果表单中的字段有 20 个呢?

const searchObj = ref(formRef.value.getFieldsValue()); // 这里是获取当前过滤表单中的所有字段的值

//这里一个个放 emmm 其实有更优雅的方式

formRef.value.setFieldsValue({state:searchObj.value.state,

name:searchObj.value.name,

number:searchObj.value.number,

siteId: ''})

以下是优化方案

// 这里获取到了用户选中的客户,这时候首先清空工地列表,然后把工地列表查出来

// 先获取当前表单中的内容

const searchObj = ref(formRef.value.getFieldsValue());

// 通过 JSON.parse = > JSON.stringify 来讲对象深拷贝

const temp = JSON.parse(JSON.stringify(searchObj.value));

// 如果当前的 siteId 不为空,设置成空的

if (temp.siteId !== undefined) {

temp.siteId = '';

}

// 表单中的字段只有 siteId 被清空,剩下的字段还在 temp 当中,再赋值给表单

//(因为执行 setFieldsValue 之后,会导致除了设置的字段以外的整个表单清空)

formRef.value.setFieldsValue({ ...temp });

参考链接

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。