【elementUi】關於el-form使用自定義校驗規則的傳參問題
需求:在很多時候,我們的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)) } }