写在最前:
我最早是没怎么接触uni-app移动端开发的,渐渐跟着工作里的一些项目边学边开发起来,所以可能记录的点也比较基础,单纯记录分享一下嘿嘿,希望也能帮到朋友们。
功能描述:
开发功能的移动端表单项通过接口给出,不定项,执行提交功能时需要处理表单校验。
解决方式:
1、结合接口给的数据,先生成一个表单格式化的数组。通过遍历这个格式化数组,将接口给的数据一个个地填入表单对象内(键值对,最好让后端出具一个各字段独立唯一的字符串属性作为表单的临时字段名,不然就自己前端按唯一的原则拼接出一套临时字段名用来存放数据)。
2、遍历格式化数组对象期间,顺便给表单rules绑定的对象依次塞入对应的校验条件,根据实际情况编辑。我这边具体实现是这样(如果是数组类型字段,初始值要给[],后续结合rules的type==array才能做到准确的判断填写情况):
form_format.forEach((element) => {
form[element.key] = element.type != "multichoice" ? "" : [];
show_loading.value = true;
let obj = [
{
required: element.need == 1,
message: "请完善 " + element.title + " 信息",
trigger: ["blur", "change"],
type: form_format_type[element.type],
},
];
rules[element.key] = obj;
});
3、有了表单格式化数组、表单数据和表单校验对象后,就可以在页面内通过表单组件循环遍历出一整个带有各自不同校验或则的动态表单了。我的实现代码如下(其实我这边代码应该还能再优化一下把循环体判断放到u-form-item上,把分支判断放到对应的u--input等控件代码上,代码量应该能缩小一些,但是暂时不想动了hhhh):
<u--form
class="desire-form"
ref="formRef"
:model="form"
:rules="rules"
labelPosition="left"
labelWidth="auto"
labelAlign="left"
errorType="message"
v-loading="!show_loading"
>
<view v-for="item in form_format" :key="item.index">
<u-form-item
:label="item.title"
:prop="item.key"
:borderBottom="true"
:required="item.need == 1"
v-if="item.type == 'text'"
>
<u--input
:placeholder="item.title"
border="none"
v-model="form[item.key]"
@change="change"
@focus="footBtn = false"
@blur="footBtn = true"
confirmType="next"
inputAlign="center"
></u--input>
</u-form-item>
<u-form-item
:label="item.title"
:prop="item.key"
:borderBottom="true"
:required="item.need == 1"
v-else-if="item.type == 'longtext'"
>
<u--textarea
v-model="form[item.key]"
confirmType="next"
:placeholder="item.title"
@focus="footBtn = false"
@blur="footBtn = true"
:maxlength="300"
autoHeight
count
></u--textarea>
</u-form-item>
<u-form-item
:label="item.title"
:prop="item.key"
:borderBottom="true"
:required="item.need == 1"
v-else-if="item.type == 'choice'"
>
<u-radio-group
v-model="form[item.key]"
placement="row"
@change="groupChange"
>
<u-radio
:customStyle="{ marginBottom: '8rpx', marginLeft: '20rpx' }"
v-for="(opt_item, index) in getIdxArr(
JSON.parse(item.options)
)"
:key="opt_item.index"
:label="JSON.parse(item.options)[index]"
:name="opt_item"
@change="radioChange"
>
</u-radio>
</u-radio-group>
</u-form-item>
<u-form-item
:label="item.title"
:prop="item.key"
:borderBottom="true"
:required="item.need == 1"
v-else-if="item.type == 'multichoice'"
>
<u-checkbox-group
v-model="form[item.key]"
placement="column"
@change="checkboxChange"
>
<u-checkbox
:customStyle="{ marginBottom: '8rpx', marginLeft: '20rpx' }"
v-for="(opt_item, index) in getIdxArr(
JSON.parse(item.options)
)"
:key="opt_item.index"
:label="JSON.parse(item.options)[index]"
:name="opt_item"
>
</u-checkbox>
</u-checkbox-group>
</u-form-item>
</view>
</u--form>
4、最后就是常规的sumit提交调用接口那一套写下去即可。
注意事项:
1、初始化表单对象时最好默认给一个默认键值对,不然可能会提示下面这个问题:
同时还可能导致表单validate方法报错或失效。
2、注意校验规则里的type一定要做到对应,不然可能控制台会有一大堆的警告,同时多选、单选这类控件在校验是否有值时会发生误判。