需求:在很多時候,我們的form表單並不是一個個寫出來的,而是通過數據遍歷渲染的,所以綁定的prop值 model值 rule值等等都不是常規的寫法
1.常規
常規的寫法:

綁定的數據格式:

但是現在,有很多輸入表單,我們不會一個一個去寫,而是通過數據了渲染(正應了VUE數據驅動試圖?)
2.需要的效果:

由於布局高度相似,所以我們可以考慮循環。
先構思數據應該是什么樣的,每一個el-form-item會包含它的綁定值v-model,規則rules,placeholder,甚至還有clearable disabled等屬性

然后通過數據去構建視圖

今天的重點是校驗規則。由於寫法不同平常,所以為每個form-item單獨配置校驗規則 :rules="item.rules"
有余自定義的校驗規則可以放在當前的vue文件中
比如:

然后在規則中直接引用
![]()
但是這樣校驗規則接沒有辦法復用,我們可以把所有的校驗規則提取成公共的JS文件,export出去,在需要用的vue文件中import進來,在對應的rules上像上邊一樣使用
這樣最大程度的解耦可以服用,但也出現問題,比如本文中的需求,所綁定的v-model的值是children里的nodel 自定義規則的參數value並不能讀取到該值
所以我這里想到通過bind傳遞this,


這里為什么寫的這么麻煩?我的初衷是通過bind綁定到this,第二個參數直接傳遞所需要的數據,但是不知道為什么,傳this可以讀取到,讀取再深一點this.boxData或者更深就讀不到了
其實在this上年是可以看到具體屬性的。知道的還請不吝賜教
所以這里我就這么傳參數了 validPercent.bind(this, this, 0, 0)
第一個參數this: 綁定到this
第二個參數this:傳遞的數據
第三個參數0:該數據所處於boxData的第一層級的index
第四個參數0:該數據所處於boxData的第二層級的index
這兩個參數都是為了方便在校驗規則里取到對應的value值,這樣就達到了傳參的目的,思路是這樣,但由於上邊說的問題,應該還可以精簡

插曲: 單個可以執行校驗,點擊確定按鈕的時候無法校驗,沒有錯誤提示
有警告![]()
只要隨便綁定一個model就可以了


3.代碼:
<template> <div class="outerDiv"> <div class="content"> <div class="form"> <el-form ref="form" :model="form"> <div v-for="(itemSum, idxSum) in boxData" :key="idxSum"> <el-divider>{{itemSum.txt}}</el-divider> <el-row> <el-col v-for="(item, idx) in itemSum.children" :key="idx" :span="8"> <el-form-item v-if="item.type==='select'" :label="item.label" :prop="item.prop" :rules="item.rules"> <el-select v-model="item.model" :placeholder="item.placeholder" size="medium" :disabled="item.disabled" clearable> <el-option v-for="val in item.options" :key="val.code" :label="val.name" :value="val.code"> </el-option> </el-select> </el-form-item> <el-form-item v-if="item.type==='input'" :label="item.label" :prop="item.prop" :rules="item.rules"> <el-input v-model.trim="item.model" size="medium" :placeholder="item.placeholder" clearable :disabled="item.disabled" clearable></el-input> </el-form-item> </el-col> </el-row> </div> </el-form> <div style="text-align: right"> <el-button class="btnnormal marginR" type="primary" disabled>修改</el-button> <el-button class="btnnormal" type="primary" @click="submitEvent">執行</el-button> </div> </div> </div> </div> </template>
<script> import { validPercent } from '@/validator/validator' export default { name: 'ALarm', data() { return { form: { }, boxData: [{ txt: '盯盤維度', children: [{ type: 'select', model: '', prop: 'user_name', label: 'PIN', placeholder: '請選擇PIN', options: [{ name: '小米', code: '小米' }], rules: { required: true, validator: validPercent.bind(this, this, 0, 0), trigger: 'change' }, disabled: false }, { type: 'input', model: '', prop: 'user_password', label: '密碼', placeholder: '請輸入密碼', rules: { required: true, validator: validPercent.bind(this, this, 0, 1), trigger: 'blur' }, disabled: true }, ] }, { txt: '觸發條件', children: [{ type: 'select', model: '', prop: 'data', label: '時間', placeholder: '請選擇時間', rules: { required: true, validator: validPercent.bind(this, this, 1, 0), trigger: 'change' }, options: [], disabled: true }, ] }, { txt: '執行操作', children: [{ type: 'select', model: '1', prop: 'optionType', label: '操作類型', placeholder: '請選擇操作類型', rules: { required: true, validator: validPercent.bind(this, this, 2, 0), trigger: 'change' }, options: [{ name: '企業微信發送通知', code: '1' }], disabled: false }, { type: 'input', model: '', prop: 'qywx_id', label: '企業微信ID', placeholder: '請輸入企業微信ID', rules: { required: true, validator: validPercent.bind(this, this, 2, 1), trigger: 'blur' }, disabled: false }, ] }, ] } }, methods: { submitEvent() { const vm = this; let data = {}
// 每個表單綁定的是對應數據中的model,字段名就是prop,這樣處理一下要提交的數據 for (let i of vm.boxData) { for (let j of i.children) { vm.$set(data, j.prop, j.model) } } vm.$refs.form.validate((valid) => { if (valid) { // 執行對應的接口操作 } }) } } } </script>
export const validPercent = (zhi, outerIdx, innerIdx, rule, value, callback) => { let iptVale = zhi.boxData[outerIdx].children[innerIdx].model let iptPlaceHolder = zhi.boxData[outerIdx].children[innerIdx].placeholder if(iptVale) { return callback() } else { return callback(new Error(iptPlaceHolder)) } }
