elmentui表單重置初始值問題與解決方法

前端cry發表於2023-09-23

背景

在做管理臺專案時,我們會經常使用到表單+表格+彈窗表單的組合,以完成對資料的增、刪、查、改

  • 在vue2+elementui專案中,使用彈窗dialog+表單form,實現對資料的新增和修改。
  • 每次關閉彈窗時,使用resetFields方法對錶單進行重置。
  • 下一次開啟彈窗時,
    • 如果是新增資料,那麼會呈現空的表單。
    • 如果是修改資料,那麼表單上已預填好了資料。

很多小夥伴可能會遇到表單重置的初始值問題,如圖。

問題具體描述為:每次關閉彈窗時,表單不是重置為我們設定的空資料,而是重置為在該頁面上第一次開啟彈窗時表單的資料

這意味著,如果我們進入頁面後第一次開啟的是修改彈窗,那麼以後每次表單重置的資料都是最開始開啟的那個修改彈窗表單的初始資料

原因

讓我們看下程式碼:

<template>
    <div>
        <!-- 新增 -->
        <el-button @click="handleAdd">新增</el-button>

        <!-- 表格 -->
        <el-table :data="tableData" style="width: 800px">
            <el-table-column prop="id" label="id" width="180" align="center" />
            <el-table-column prop="name" label="名稱" width="180" align="center" />
            <el-table-column label="操作" align="center">
                <template v-slot="{ row }">
                    <el-button @click="handleEdit(row)">修改</el-button>
                </template>
            </el-table-column>
        </el-table>

        <!-- 彈窗 -->
        <el-dialog title="新增/修改" :visible.sync="dialogVisible" width="30%" :before-close="handleClose" center>
            <template>
                <div>
                    <el-form ref="form" :model="formData">
                        <el-form-item prop="name" label="名稱">
                            <el-input v-model="formData.name"></el-input>
                        </el-form-item>
                        <el-form-item prop="id" label="id">
                            <el-input v-model="formData.id"></el-input>
                        </el-form-item>
                    </el-form>
                </div>
            </template>
            <template #footer>
                <el-button type="primary">確定</el-button>
                <el-button type="info">取消</el-button>
            </template>
        </el-dialog>
    </div>
</template>

<script>
export default {
    name: 'formInitial',
    data() {
        return {
            tableData: [
                { id: 1, name: '王小虎' },
                { id: 2, name: '劉小白' },
                { id: 3, name: '張曉來' },
            ],
            formData: {
                name: '',
                id: '',
            },
            dialogVisible: false,
        };
    },
    methods: {
        // 新增
        handleAdd() {
            this.dialogVisible = true;
        },
        // 編輯  !!! 問題所在 !!!
        handleEdit(row) {
            // 給表單賦初值
            this.formData.name = row.name;
            this.formData.id = row.id;
            // 開啟彈窗
            this.dialogVisible = true;
        },
        // 彈窗關閉
        handleClose() {
            // 初始資料
            this.$refs.form.resetFields();
            // 關閉彈窗
            this.dialogVisible = false;
        }
    },
};
</script>

這裡我們重點關注handleEdit() 這個方法。

表面上看並沒有什麼問題,每次點選修改,開啟彈窗前,表單賦初值。

這裡就不跟大夥兒賣關子了,原因:

  • 一開始彈窗隱藏時,彈窗樣式加上了display: none 屬性。
  • display: none 屬性的作用:將元素從DOM結構中完全移除。
  • 而表單是放在彈窗裡的,意味著表單一開始不會出現在頁面結構中,此時data 中的預設資料formData 並沒有作用上表單。
  • 當點選修改時,觸發handleEdit() 方法,修改了formData 。此時彈窗開啟,新的formData 作用上表單,並且表單將新的formData當作了初始資料

解決

解決思路很簡單,就是想辦法讓表單吃上原始的formData

原來是先賦資料,再開啟彈窗。那麼現在改為先開啟彈窗,再賦資料。

只需要修改handleEdit()方法:

// 編輯
handleEdit(row) {
    // 開啟彈窗
    this.dialogVisible = true;
    // 等到下次DOM渲染完成,即彈窗完全顯示後執行
    this.$nextTick(() => {
        // 給表單賦初值
        this.formData.name = row.name;
        this.formData.id = row.id;
    });
},

這裡用到this.$nextTick() ,是為了保證賦值是發生在彈窗開啟後,所以彈窗開啟的那一刻,表單使用的還是最初data中的formData ,並將其作為表單初始值。

相關文章