使用uniapp+uview开发微信小程序,需求中要涉及到常规表单+API返回的动态表单,并对表单添加验证规则。在实现过程中遇到视图中动态表单数据不即时显示,错误提示不即时消除等问题。就此次踩坑做个记录,便于遇到同样问题的小伙伴。
构建表单数据、验证规则
尝试过在data()中直接写完表单验证规则,然后在应用到<u--from>中,发现校验规则未生效,于是就计划与构建动态表单数据时,一并构建验证规则。
data(){
info: {
exFields: [],
},
formData: {
name: "",
extra: {}
},
errorType: 'message',
fileList: {}, // 图片组件上传图片后预览上传
},
methods: {
async handleActivityInfo(id){
try {
const res = 后端请求返回
this.info.exFields = res.extra_fields
this.handleExFields(this.info.exFields)
} catch(error) {
console.log(error)
}
},
handleExFields(fields){
// 此处动态字段的构建,根据后端接收数据的形式进行调整
fields.forEach(item => {
this.formData.extra[`extra_${item.id}`] = null
this.fileList[`extra_${item.id}`] = []
})
this.handleRules()
},
handleRules() {
// 非动态字段部分的验证规则
const rules = {
'name': {
type: "string",
required: true,
message: "请输入真实姓名",
trigger: ["blur", "change"]
},
}
// 基于动态字段,构建动态字段的验证规则
this.info.exFields.forEach(item => {
Object.assign(rules, {
[`extra.extra_${item.id}`]: {
type: item.field_type === 1 ? 'string' : 'string',
required: true,
message: item.field_type === 1 ? `请输入${item.field_name}` : `请上传${item.field_name}`,
trigger: ['blur', 'change'],
}
})
});
}
this.rules = rules
this.show = true
// 表单绑定验证规则
this.$refs.uForm.setRules(this.rules)
}
视图部分
v-if="show",想着是数据未准备好时,不展示视图,避免提前渲染后相关规则不生效。
<view v-if="show">
<u--form ref="uForm" :model="formData" :rules="rules" labelPosition="top" :errorType="errorType">
<view class="item">
<u-form-item label="姓名" prop="name">
<u--input v-model="formData.name" placeholder="请输入真实姓名"></u--input>
</u-form-item>
</view>
<view v-for="(item, index) in info.exFields" :key="item.id">
<view class="item" v-if="item.field_type == 1">
<u-form-item :label="item.field_name" :prop="`extra.extra_${item.id}`">
<u--input
v-model="formData.extra[`extra_${item.id}`]"
:placeholder="`请输入${item.field_name}`"
@blur="(e) => handleValidateField(e,item.id)"
></u--input>
</u-form-item>
</view>
<view class="item" v-else>
<u-form-item :label="item.field_name" :prop="`extra.extra_${item.id}`">
<u-upload
:fileList="fileList[`extra_${item.id}`]"
accept="image"
@afterRead="(e) => handleAfterRead(e,item.id)"
@delete="(e) => handleDeletePic(e, item.id)"
:name="`photo_${index}`"
imageMode="widthFix"
:maxCount="1"
></u-upload>
</u-form-item>
</view>
</view>
</u--form>
</view>
数据校验
按照前面两部分处理后,能进行数据校验,但是也带来两个问题: 1、视图数据不及时更新,代码console.log却能看到最新的数据; 2、错误提示不自动消失;
处理方式:
表单的验证规则是异步的,所以采用异步的方式进行数据的校验。然后再使用this.$forceUpdate()进行视图数据刷新
async handleValidateField(e,index) {
try{
await this.$refs.uForm.validateField(`extra.extra_${index}`)
this.$refs.uForm.clearValidate(`extra.extra_${index}`)
this.$forceUpdate()
} catch(error) {
console.log(error)
}
},
async handleAfterRead(e, index){
const { file } = e
this.fileRule.folderName = `${this.fileRule.folderName}/${this.info.id}`
uploadCos(file, this.fileRule.folderName, async res => {
if(res) {
const {name, url, location} = res
this.formData.extra[`extra_${index}`] = location
// 预览图片
this.fileList[`extra_${index}`] = [{url: `https://${location}`}]
try {
await this.$refs.uForm.validateField(`extra.extra_${index}`)
this.$refs.uForm.clearValidate(`extra.extra_${index}`)
this.$forceUpdate()
} catch (error) {
console.log(error)
}
}
})
},
以上为动态表单数据校验、数据不及时更新的一种处理方式。各位大佬有更好的方式,还请指导指导。