首頁 > 軟體

el-form resetFields無效和validate無效的可能原因及解決方法

2022-08-12 14:00:19

問題匯入

在使用 el-form 過程中,尤其是表單驗證這一塊,官方提供的 reserFields 方法以及驗證方面存在一些坑,在此記錄一下,給大家提供可能的解決辦法。

簡單範例

1、官方案例

先來看看官方提供的案例,對應的官網 表單驗證

對應的程式碼

<el-form :model="ruleForm" :rules="rules" ref="ruleForm" label-width="100px" class="demo-ruleForm">
  <el-form-item label="活動名稱" prop="name">
    <el-input v-model="ruleForm.name"></el-input>
  </el-form-item>
  <el-form-item label="活動區域" prop="region">
    <el-select v-model="ruleForm.region" placeholder="請選擇活動區域">
      <el-option label="區域一" value="shanghai"></el-option>
      <el-option label="區域二" value="beijing"></el-option>
    </el-select>
  </el-form-item>
  <el-form-item label="活動時間" required>
    <el-col :span="11">
      <el-form-item prop="date1">
        <el-date-picker type="date" placeholder="選擇日期" v-model="ruleForm.date1" style="width: 100%;"></el-date-picker>
      </el-form-item>
    </el-col>
    <el-col class="line" :span="2">-</el-col>
    <el-col :span="11">
      <el-form-item prop="date2">
        <el-time-picker placeholder="選擇時間" v-model="ruleForm.date2" style="width: 100%;"></el-time-picker>
      </el-form-item>
    </el-col>
  </el-form-item>
  <el-form-item label="即時配送" prop="delivery">
    <el-switch v-model="ruleForm.delivery"></el-switch>
  </el-form-item>
  <el-form-item label="活動性質" prop="type">
    <el-checkbox-group v-model="ruleForm.type">
      <el-checkbox label="美食/餐廳線上活動" name="type"></el-checkbox>
      <el-checkbox label="地推活動" name="type"></el-checkbox>
      <el-checkbox label="線下主題活動" name="type"></el-checkbox>
      <el-checkbox label="單純品牌曝光" name="type"></el-checkbox>
    </el-checkbox-group>
  </el-form-item>
  <el-form-item label="特殊資源" prop="resource">
    <el-radio-group v-model="ruleForm.resource">
      <el-radio label="線上品牌商贊助"></el-radio>
      <el-radio label="線下場地免費"></el-radio>
    </el-radio-group>
  </el-form-item>
  <el-form-item label="活動形式" prop="desc">
    <el-input type="textarea" v-model="ruleForm.desc"></el-input>
  </el-form-item>
  <el-form-item>
    <el-button type="primary" @click="submitForm('ruleForm')">立即建立</el-button>
    <el-button @click="resetForm('ruleForm')">重置</el-button>
  </el-form-item>
</el-form>
<script>
  export default {
    data() {
      return {
        ruleForm: {
          name: '',
          region: '',
          date1: '',
          date2: '',
          delivery: false,
          type: [],
          resource: '',
          desc: ''
        },
        rules: {
          name: [
            { required: true, message: '請輸入活動名稱', trigger: 'blur' },
            { min: 3, max: 5, message: '長度在 3 到 5 個字元', trigger: 'blur' }
          ],
          region: [
            { required: true, message: '請選擇活動區域', trigger: 'change' }
          ],
          date1: [
            { type: 'date', required: true, message: '請選擇日期', trigger: 'change' }
          ],
          date2: [
            { type: 'date', required: true, message: '請選擇時間', trigger: 'change' }
          ],
          type: [
            { type: 'array', required: true, message: '請至少選擇一個活動性質', trigger: 'change' }
          ],
          resource: [
            { required: true, message: '請選擇活動資源', trigger: 'change' }
          ],
          desc: [
            { required: true, message: '請填寫活動形式', trigger: 'blur' }
          ]
        }
      };
    },
    methods: {
      submitForm(formName) {
        this.$refs[formName].validate((valid) => {
          if (valid) {
            alert('submit!');
          } else {
            console.log('error submit!!');
            return false;
          }
        });
      },
      resetForm(formName) {
        this.$refs[formName].resetFields();
      }
    }
  }
</script>

對應的欄位含義,在官網上都有詳細的解釋,那麼如果類似的表單重置 resetFields 時候無法成功,那麼可能的原因有哪些呢?(以下皆由個人實踐得出,具體原因有些不太懂,歡迎解釋補充)

resetFields 失敗可能原因

1: el-form 中使用 v-model="ruleForm"代替了:model="ruleForm",正確的應為後者。

2: el-form-item 中的 prop 屬性設定錯誤,官網給出瞭解釋。即 prop=a, v-model=Form.a,Js中表單資料欄位Form:{ a:'', b: [] },需要一一對應,不能出現差錯。

3: <el-button @click="resetForm('ruleForm')">重置</el-button> resetForm(formName)的引數一定要和 el-formref ="formName"一致。

2、個人案例

專案開發過程中,通常 el-form 都是巢狀在el-dialog中。在表格頁面中,點選新增或者修改按鈕,彈出同一個表單,因為兩個操作都是類似的元件,不同的元件可以用 v-if 遮蔽掉,這也是大多數開發中公用元件的一個體現。

舉個個例:

通過新增按鈕和編輯按鈕都能夠開啟這個dialog。

EditRole.vue

<template>
    <div style="text-align: left;">
        <el-button class="add-button" type="success" @click="dialogFormVisible = true">新增角色</el-button>
        <el-dialog
            :title="title"
            :visible.sync="dialogFormVisible"
            @close="clear" >
            <el-form :model="form"  ref="roleForm" :rules="rules">
                <el-form-item label="角色名稱" :label-width="formLabelWidth" prop="name">
                    <el-input v-model="form.name" autocomplete="off" placeholder="請輸入新角色英文名稱"></el-input>
                </el-form-item>
                <el-row>
                    <el-col :span="16">
                        <el-form-item label="中文名稱" :label-width="formLabelWidth" prop="nameZh">
                            <el-input v-model="form.nameZh" autocomplete="off" placeholder="請輸入中文名稱"></el-input>
                        </el-form-item>
                    </el-col>
                    <el-col :span="8">
                        <el-form-item label="是否可用" :label-width="formLabelWidth" prop="enabled">
                            <el-switch
                                v-model="form.enabled"
                                :active-value="1"
                                :inactive-value="0"
                                active-color="#13ce66"
                                inactive-color="#ff4949">
                            </el-switch>
                        </el-form-item>
                    </el-col>
                </el-row>
                <el-form-item label="功能簡述" :label-width="formLabelWidth" prop="description">
                    <el-input v-model="form.description" autocomplete="off"  type="textarea"
                              :autosize="{ minRows: 2, maxRows: 4}" placeholder="請輸入角色功能簡述"></el-input>
                </el-form-item>
                <el-form-item prop="id" style="height: 0">
                    <el-input type="hidden" v-model="form.roleId" autocomplete="off"></el-input>
                </el-form-item>
            </el-form>
            <div slot="footer" class="dialog-footer">
                <el-button @click="dialogFormVisible = false">取 消</el-button>
                <el-button type="info" @click="resetForm('form')">重置</el-button>
                <el-button type="primary" @click="submitForm('roleForm')">確 定</el-button>
            </div>
        </el-dialog>
    </div>
</template>

<script>
export default {
    name: "EditRole",
    data () {
        return {
            form: {
                roleId: '',
                name: '',
                nameZh: '',
                enabled: 1,
                description: '',
            },
            // 表單驗證規則
            rules: {
                name: [
                    { required: true, message: '請輸入新角色英文名稱', trigger: 'blur' },
                ],
                nameZh: [
                    { required: true, message: '請輸入角色中文名稱', trigger: 'blur' },
                ],
                description: [
                    { required: true, message: '請賦予角色簡要的功能描述', trigger: 'blur' }
                ],
            },
            dialogFormVisible: false,
            formLabelWidth: '120px',
            isShow: true, //是否顯示父級選單,新增的時候顯示,修改的時候不讓修改父級選單。
            title: '新增角色',
        }
    },
   
    methods: {
        clear () {
            if (this.form.id !== '') {
                // 不為空,那麼就是修改操作
                this.isShow = false;
                this.title = '修改角色'
            }
            // 關閉彈框後清空資料,
            this.resetForm('roleForm')
            this.isShow = true;
            this.title = '新增角色'
        },
        resetForm(formName) {
            // 重置表格內容
            this.$refs[formName].resetFields();
        },
        submitForm (formName) {
            this.$refs[formName].validate((valid) => {
                if (valid) {
                    ...
                }else {
                    this.$notify({
                        type: 'error',
                        message: '資料未填寫完整,請仔細核對!'
                    })
                    return false;
                }
            })

        },
    }
}
</script>

<style scoped>
    .add-button {
        margin: 18px 0 0 10px;
    }
</style>

resetFields失效及解決辦法

先新增後編輯

一般開啟這個頁面後,我們測試資料的時候,都是先點選新增按鈕,關閉dialog後,再點選編輯按鈕。

此時你使用this.$refs[formName].resetFields(); 是能夠將表單重置為空的,因為初始化的時候,本來form資料就是空的。

先編輯後新增

但是若你先點選編輯按鈕,通過父元件傳遞了 本行資料el-dialog 的 el-form 時,退出後再點選新增按鈕,此時會發現資料被汙染,表單竟然不是空的,而是出現了剛才編輯那行的資料。圖示:

關閉彈窗時,我們設定了clear函數,clear函數為關閉dialog執行的函數。其中呼叫了resetForm函數,即利用this.$refs[formName].resetFields()來希望重置資料。但是再點選新增按鈕時,資料並沒有清除。

這個現象的原因是因為dialog是懶載入的,通過表格中的編輯按鈕開啟dialog時,傳過來了父元件行資料。即初始化時資料並不是空的,而resetFields() 函數重置時,初始化的值是啥就是啥

瞭解本質後,那麼解決這個問題就簡單了,我們關閉彈出時,不使用resetFields()函數不就行了。而是這樣:

	resetForm(formName) {
        console.log("誰要重置資料啊?" + formName)
        // 重置表格內容
        this.form= {
            roleId: '',
            name: '',
            nameZh: '',
            enabled: 1,
            description: '',
        }
	},

改動後結果:

相當於編輯退出後,將form表單初始化為空,這樣就無法出現汙染了。但是這樣也有個問題,重置資料後,無法移除校驗效果。好在官方給了我們方法,只需要新增一行。

	resetForm(formName) {
        console.log("誰要重置資料啊?" + formName)
        // 重置表格內容
        this.form= {
            roleId: '',
            name: '',
            nameZh: '',
            enabled: 1,
            description: '',
        },
        // 不使用resetFields後,重置時無法移除校驗效果,使用以下函數移除
        this.$refs[formName].clearValidate();
	},

validate失效及解決辦法

當使用表單驗證的時候,如果正常的驗證都無誤,提交時,我們通過以下程式碼來判斷是否驗證成功。

	submitForm (formName) {
        this.$refs[formName].validate((valid) => {
            if (valid) {
                ...
            }else {
                this.$notify({
                    type: 'error',
                    message: '資料未填寫完整,請仔細核對!'
                })
                return false;
            }
        })

    },

但是使用自定義驗證規則是,注意規則中回撥函數callback()一定要寫,官方檔案也寫的十分清楚。否則 if(valid) 條件無法判斷,而且它是沒有報錯的。

如自定義郵箱校驗的時候:

	data() {
        const validateEmail = (rule, value, callback) => {
            let regEmail = /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(.[a-zA-Z0-9_-])+/;
            if (!regEmail.test(this.form.email)) {
                return callback(new Error("郵箱格式不正確")); // 有一個if 就要 一個 callback
            }
            return callback(); // 返回一個回撥函數給驗證,是表單validate生效
        };
        return {
            // 表單資料
            form: {
                user_id: '',
                ...
                email: '',
            },
            // 表單驗證規則
            rules: {
 				...
                email: [
                    { required: true, message: '請輸入真實郵箱地址,方便找回密碼', validator: validateEmail, trigger: 'blur' },
                ],
            },
        }
    },

callback() 回撥函數必須要被呼叫。

這是目前碰到的表單問題,大家有什麼好的解決方案或者新問題,歡迎在評論區留言,幫助大家解決問題!

3、model is required for validate to work!

2021/4/21

今天給表的表單新增驗證規則的時候,el-form-item都設定好了prop屬性,但是無效,F12後給出一個警告

然後回去看el-form時候,才發現 v-model = 沒有改成 :model,造成錯誤,在此更新一下。

結尾

到此這篇關於el-form resetFields無效和validate無效的可能原因及解決方法的文章就介紹到這了,更多相關el-form resetFields無效和validate無效內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com