Element Form表單實踐(下)

做者:小土豆biubiubiujavascript

博客園:www.cnblogs.com/HouJiao/css

掘金:juejin.im/user/58c61b…html

微信公衆號:土豆媽的碎碎念(掃碼關注,一塊兒吸貓,一塊兒聽故事,一塊兒學習前端技術)前端

碼字不易,點贊鼓勵喲~vue

前言

上一篇文章 Element Form表單實踐(上)參照着文檔將表單部份內容實踐了一下。java

這篇文章將分享項目開發中的一個表單實踐,最終作出來的效果大體是下面這個樣子:npm

這個表單看似是比較簡單的,但實際上比通常表單存在一些細節的東西須要設計和處理。element-ui

接下來就來完成這個功能。後端

主頁面

首先是主頁面的實現。微信

主頁面的邏輯很是簡單,直接將代碼貼出來。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Element Form表單實踐</title>
    <!-- 開發環境版本,包含了有幫助的命令行警告 -->
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

    <!-- 引入樣式 -->
    <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
    <!-- 引入組件庫 -->
    <script src="https://unpkg.com/element-ui/lib/index.js"></script>
    
</head>
<body>
    <div id="box">
        <el-form label-suffix=":" :model="form" label-width="80px" ref="form">
            <el-form-item label="名稱" prop="name" :rules="[{ required:true, trigger: 'blur', message: '名稱是必填項' }]">
                <el-input v-model="form.name"></el-input>
            </el-form-item>
            <el-form-item label="選項">
                <el-switch v-model="form.item"></el-switch>
                <el-button :disabled="!form.item" type="primary" size="small">詳細配置</el-button>
            </el-form-item>
            <el-form-item>
                <el-button type="primary" size="small" @click="saveInfo">保存</el-button>
            </el-form-item>
        </el-form>   
    </div>
    <script> var vm = new Vue({ el: '#box', data: { form: { name: "", item: false } }, methods: { saveInfo() { this.$refs['form'].validate((valid,failedInfo) => { if(valid){ // 提示用戶 this.$message({ message: '保存成功', type: "success", center: true }); }else{ return false; } }) } } }) </script>
</body>
</html>
複製代碼

這段代碼中的內容都是上一篇文章中實踐過的,沒有什麼特別須要說明的點。

詳細配置頁面

簡單實現

詳細配置頁面實際上也是一個表單,咱們先來把界面中須要展現的組件畫出來。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Element Form表單實踐</title>
    <!-- 開發環境版本,包含了有幫助的命令行警告 -->
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

    <!-- 引入樣式 -->
    <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
    <!-- 引入組件庫 -->
    <script src="https://unpkg.com/element-ui/lib/index.js"></script>
    
</head>
<body>
    <div id="box">
        <el-form label-suffix=":" :model="form" label-width="80px" ref="form">
            <el-form-item label="名稱" prop="name" :rules="[{ required:true, trigger: 'blur', message: '名稱是必填項' }]">
                <el-input v-model="form.name"></el-input>
            </el-form-item>
            <el-form-item label="選項">
                <el-switch v-model="form.item"></el-switch>
                <el-button :disabled="!form.item" type="primary" size="small" @click="modelVisible=true">詳細配置</el-button>
            </el-form-item>
            <el-form-item>
                <el-button type="primary" size="small" @click="saveInfo">保存</el-button>
            </el-form-item>
        </el-form> 
         <!-- 詳細配置 -->
        <el-dialog title="詳細配置" :visible.sync="modelVisible">
            <el-form ref="detailForm">
                <el-form-item>
                    <el-checkbox label="personalInfo">我的信息</el-checkbox>
                </el-form-item>
                <el-form-item label="年齡">
                    <el-input></el-input>
                </el-form-item>
                <el-form-item label="身高">
                    <el-input></el-input>
                </el-form-item>              
                <el-form-item>
                    <el-checkbox label="addressInfo">住址信息</el-checkbox>
                </el-form-item>
                <el-form-item label="省份">
                    <el-input></el-input>
                </el-form-item>
                <el-form-item label="城市">
                    <el-input></el-input>
                </el-form-item>
                <el-form-item>
                    <el-button type="primary">保存</el-button>
                    <el-button type="primary">重置</el-button>
                </el-form-item>
            </el-form>
        </el-dialog>  
    </div>
    <script> var vm = new Vue({ el: '#box', data: { modelVisible: false, form: { name: "", item: false } }, methods: { saveInfo() { this.$refs['form'].validate((valid,failedInfo) => { if(valid){ // 提示用戶 this.$message({ message: '保存成功', type: "success", center: true }); }else{ return false; } }) } } }) </script>
</body>
</html>
複製代碼

上面這段代碼主要添加了兩個邏輯:彈窗組件和彈窗內部的表單組件

彈窗組件

彈窗組件使用的是elementdialog來實現。

主要的邏輯包含定義彈窗是否顯示的data數據modelVisible、點擊詳細配置設置彈框可見以及彈窗組件的使用。

定義彈窗是否顯示的data數據modelVisible:

var vm = new Vue({
    data: {
        // 彈窗是否顯示
        modelVisible: false
    }
})
複製代碼

點擊詳細配置設置彈框可見:

<!-- 點擊按鈕設置彈窗可見 -->
 <el-button :disabled="!form.item" type="primary" size="small" @click="modelVisible=true">詳細配置</el-button>
複製代碼

彈框組件使用:

<el-dialog title="詳細配置" :visible.sync="modelVisible">
        <!-- 省略表單代碼 -->
</el-dialog>        
複製代碼

彈窗組件的實現和使用很是簡單,沒有特別須要說明的點。

最後在看一下效果。

表單組件

表單組件的代碼以下:

<el-form ref="detailForm">
    <el-form-item>
        <el-checkbox label="personalInfo">我的信息</el-checkbox>
    </el-form-item>
    <el-form-item label="年齡">
        <el-input></el-input>
    </el-form-item>
    <el-form-item label="身高">
        <el-input></el-input>
    </el-form-item>              
    <el-form-item>
        <el-checkbox label="addressInfo">住址信息</el-checkbox>
    </el-form-item>
    <el-form-item label="省份">
        <el-input></el-input>
    </el-form-item>
    <el-form-item label="城市">
        <el-input></el-input>
    </el-form-item>
    <el-form-item>
        <el-button type="primary">保存</el-button>
        <el-button type="primary">重置</el-button>
    </el-form-item>
</el-form>
複製代碼

能夠看到,表單組件的代碼很是的簡單,前一篇文章中實踐的內容這裏都尚未添加。

那接下來結合本節須要實現的這個功能添加上一節中實踐過的內容。

表單添加model屬性

首先第一個最重要的就是表單的model屬性,也就是表單綁定的數據。

這裏咱們先定義一個簡單的表單數據

detailConfigForm: {
    personalInfo: false, // 我的信息
    age:'',              // 年齡
    height: '',          // 身高
    addressInfo: true,  // 住址信息
    province: '',        // 省份
    city: ''             // 城市
}
複製代碼

而後將該數據綁定到表單上,同時爲表單項(el-form-item)添加modelprop屬性。

<el-form ref="detailForm" label-width="80px" :model="detailConfigForm">
    <el-form-item prop="personalInfo" >
        <el-checkbox label="personalInfo" v-model="detailConfigForm.personalInfo">我的信息</el-checkbox>
    </el-form-item>
    <el-form-item label="年齡" prop="age">
        <el-input v-model="detailConfigForm.age"></el-input>
    </el-form-item>
    <el-form-item label="身高" prop="height">
        <el-input v-model="detailConfigForm.height"></el-input>
    </el-form-item>              
    <el-form-item prop="addressInfo">
        <el-checkbox label="addressInfo" v-model="detailConfigForm.addressInfo">住址信息</el-checkbox>
    </el-form-item>
    <el-form-item label="省份" prop="province">
        <el-input v-model="detailConfigForm.province"></el-input>
    </el-form-item>
    <el-form-item label="城市" prop="city">
        <el-input v-model="detailConfigForm.city"></el-input>
    </el-form-item>
    <el-form-item>
        <el-button type="primary">保存</el-button>
        <el-button type="primary">重置</el-button>
    </el-form-item>
</el-form>
複製代碼

完成後,此時在表單中填寫內容已經沒有問題了。

我的信息/住址信息啓用禁用

接着須要實現的功能是:將我的信息/住址信息當作一個開關選中時對應模塊的控件啓動,能夠正常填寫內容;取消選中時,對應的模塊控件禁用,且清空上一次填寫的內容。

那咱們知道表單項設置disabled值就能夠實現。

根據前面描述禁用啓用的邏輯,能夠發現我的信息/住址信息啓用禁用表單禁用啓用恰好是相反的邏輯。

因此目前實現的思路就是:將detailConfigForm.personalInfo的值取反綁定在年齡身高控件的disabled屬性上;將detailConfigForm.addressInfo的值取反綁定在省份城市控件的disabled屬性上。

這裏咱們只將我的信息部分的邏輯實現代碼貼出來

<el-form-item label="年齡" prop="age">
    <el-input v-model="detailConfigForm.age" :disabled="!detailConfigForm.personalInfo"></el-input>
</el-form-item>
<el-form-item label="身高" prop="height">
    <el-input v-model="detailConfigForm.height" :disabled="!detailConfigForm.personalInfo"></el-input>
</el-form-item>
複製代碼

在來看下效果。

地址信息這部分的禁用啓用邏輯和我的信息是相同的,這裏不在多說

取消啓用清空對應控件中填寫的內容

那接下來要實現的功能就是取消啓用清空對應控件中填寫的內容

方式一:手動賦空值

上一節的 Element Form表單實踐(上) 中說過表單的resetFileds方法能夠重置表單。

this.refs['formName'].resetFields()
複製代碼

不過該方法會重置表單中的全部屬性,因此說不太符合咱們的要求。咱們只須要重置部分表單:即我的信息取消啓用時,只須要清空年齡身高這兩個內容便可。

解決這個問題的思路之一就是放棄使用resetFields方法,直接給表單數據賦空值從而清空表單內容

清空表單內容這個操做是在我的信息啓用和禁用的時候執行的,即在detailConfigForm.personalInfo值發生變化時執行的,那這個很天然的就會想到使用vue watch 屬性監聽detailConfigForm.personalInfo的變化,在該值爲false的時候,給表單數據賦值爲空,實現清空表單內容

watch: {
    'detailConfigForm.personalInfo': function(val){
        if(val == false){
            this.detailConfigForm.age = "";
            this.detailConfigForm.height = "";
        }
    }
},
複製代碼

然而在真正的項目實踐中,當取消啓用我的信息時,須要清空的表單數量不止兩個,而是有多個,因此做者就放棄了這種手動賦值清空的方式。

放棄這種方式的緣由還有一個,就是表單的驗證也會存在問題。

表單填寫完成後,點擊提交,假如我的信息沒有啓用,那驗證時就不須要對年齡和身高進行驗證,而表單的驗證方法validate是對整個表單進行校驗的方法。

這幾個因素是我放棄手動賦值清空方式的重要緣由。

方式二:resetFileds

放棄手動賦值清空表單的這種方式後,我又迴歸到了表單的resetFields方法。既然還想使用resetFields方法,惟一的辦法就是作一個表單嵌套

這樣當我的信息取消啓用時,就能夠調用this.refs['personalInfoForm'].resetFields()重置我的信息這部分的表單內容。而在整個表單提交驗證的時候,也能夠分別調用this.refs['personalInfoForm'].validate()this.refs['addressInfoForm'].validate()分開進行驗證。

修改數據結構

那這種實現思路的第一步就是將表單的數據結構進行修改。

detailConfig: {
    personalInfoConfig:{
        personalInfo: false,       // 我的信息
        age: '',                   // 我的信息-年齡
        height: '',                // 我的信息-年齡
    },
    addressInfoConfig:{
        addressInfo: false,        // 地址信息
        province: '',              // 地址信息-省份
        city: ''                   // 地址信息-城市
    }
}
複製代碼
重寫表單代碼

接下來就須要根據這樣的數據結構將el-form表單的代碼進行重寫。

<el-form :model="detailConfig" ref="detailForm">
    <!-- 我的信息 -->
    <!-- el-form的model綁定detailConfig.personalInfoConfig -->
    <el-form :model="detailConfig.personalInfoConfig" label-width="80px" lable-suffix=":" ref="personalInfoForm">
        <el-form-item prop="personalInfo">
            <el-checkbox label="personalInfo" v-model="detailConfig.personalInfoConfig.personalInfo">我的信息</el-checkbox>
        </el-form-item>
        <el-form-item label="年齡" prop="age">
            <el-input v-model.number="detailConfig.personalInfoConfig.age" :disabled="!detailConfig.personalInfoConfig.personalInfo"></el-input>
        </el-form-item>
        <el-form-item label="身高" prop="height">
            <el-input v-model.number="detailConfig.personalInfoConfig.height" :disabled="!detailConfig.personalInfoConfig.personalInfo"></el-input>
        </el-form-item>
    </el-form>
    
    <!-- 住址信息 -->
    <!-- el-form的model綁定detailConfig.addressInfoConfig -->
    <el-form :model="detailConfig.addressInfoConfig" label-width="80px" lable-suffix=":" ref="addressInfoForm">
    <el-form-item prop="addressInfo">
        <el-checkbox v-model="detailConfig.addressInfoConfig.addressInfo" label="addressInfo">住址信息</el-checkbox>
    </el-form-item>
    <el-form-item label="省份" prop="province">
        <el-input v-model="detailConfig.addressInfoConfig.province" :disabled="!detailConfig.addressInfoConfig.addressInfo"></el-input>
    </el-form-item>
    <el-form-item label="城市" prop="city">
        <el-input v-model="detailConfig.addressInfoConfig.city" :disabled="!detailConfig.addressInfoConfig.addressInfo"></el-input>
    </el-form-item>
    <el-form-item>
        <el-button type="primary">保存</el-button>
        <el-button type="primary">重置</el-button>
    </el-form-item>
</el-form>
複製代碼
使用resetFileds

接着在修改一下watch代碼。

watch:{
    "detailConfig.personalInfoConfig.personalInfo": function(personalInfo){
        if(personalInfo == false){
            this.$refs['personalInfoForm'].resetFields()
        }
    },
    "detailConfig.addressInfoConfig.addressInfo": function(addressInfo){
        if(addressInfo == false){
            this.$refs['addressInfoForm'].resetFields()
        }
    }
},
複製代碼

能夠看到watch代碼內部就能夠直接使用表單的resetFields方法,對我的信息住址信息分開進行清空。

最終的結果和手動賦值清空是同樣的,這裏不在演示。

表單驗證

最後一個就是表單的驗證了。

rules

首先咱們須要編寫表單的rules驗證規則。

detailConfig: {
    personalInfoConfig:{
        personalInfo: false,
        age: '',
        height: '',
        rules: {
            age: [{
                type: 'number',
                message: '年齡必須爲數字值'
            }],
            height: [{
                type: 'number',
                message: '身高必須爲數字值'
            }]
        }
    },
    addressInfoConfig:{
        addressInfo: false,
        province: '',
        city: '',
        rules: {
            province: [
                { min: 2, max: 10, message: '長度必須在2-10個字符'}
            ],
            city: [
                { min: 2, max: 10, message: '長度必須在2-10個字符' }
            ]
        }
    }
}
複製代碼

新增的驗證規則以下:

年齡和身高:必須爲數值;  
省份和城市:長度必須在2-10個字符。
複製代碼

使用validate

接着在保存按鈕的click事件上綁定saveConfig方法。

<el-button type="primary" @click="saveConfig">保存</el-button>
複製代碼

接着編寫saveConfig的邏輯。

須要說明的是,只有對應的按鈕啓用了,纔會對對應啓用的表單作驗證

saveConfig(){
    // 若是我的信息啓用,則須要對我的信息下的年齡、身高字段進行驗證。
    if(this.detailConfig.personalInfoConfig.personalInfo){
        this.$refs['personalInfoForm'].validate((valid,failedInfo) => {
             // 我的信息下的年齡、身高字段進行驗證經過。
            if(valid){
                // 判斷地址信息是否啓用,啓用的話須要對地址信息下的城市、省份進行驗證
                if(this.detailConfig.personalInfoConfig.personalInfo){
                    this.$refs['addressInfoForm'].validate((valid,failedInfo) => {
                        // 地址信息下的城市、省份驗證成功。關閉dialog
                        if(valid){
                            this.modelVisible = false;
                        }else{
                            return false;
                        }
                    })
                }else{
                    this.modelVisible = false;
                }
            }else{
                return false;
            }
        })
    // 若是地址信息啓用,則須要對地址信息下的省份、城市字段進行驗證。 
    }else if(this.detailConfig.addressInfoConfig.addressInfo){
        this.$refs['addressInfoForm'].validate((valid,failedInfo) => {
            if(valid){
                this.modelVisible = false;
            }else{
                return false;
            }
        })  
    // 我的信息和地址信息均沒有啓用,直接關閉dialog 
    }else{
        this.modelVisible = false;
    }                    
},
複製代碼

這部分的邏輯比較繁瑣,由於存在啓用驗證不啓用就不驗證的邏輯判斷

完成後,最終的效果咱們再來看一下。

重置表單

首先在頁面上添加劇置按鈕,綁定事件。

<el-button type="primary" @click='resetForm'>重置</el-button>
複製代碼

接着就來使用表單的重置方法resetFileds來重置表單的內容。

那這裏須要注意的一點就是咱們的表單是嵌套表單。

直接調用外層表單resetFileds方法沒有辦法去重置表單內容。所以這裏必須調用內層表單的resetFileds方法。

resetForm(formName){
    this.$refs['personalInfoForm'].resetFields();
    this.$refs['addressInfoForm'].resetFields();
    // 調用外層表單的`resetFileds`方法沒有辦法去重置表單內容
    // this.$refs['detailForm'].resetFields();
}
複製代碼

表單重置這裏就不貼演示結果了

功能優化和bug修復

到這裏咱們表單的大部分功能已經實現了:表單禁用啓用表單禁用時清空表單內容表單驗證表單重置

那接下來就須要對實現的這個功能進行在思考。

功能優化

第一個是功能優化。

回頭看全部實現的功能,惟一以爲不太合適的地方就是表單的驗證邏輯。

saveConfig(){
    // 若是我的信息啓用,則須要對我的信息下的年齡、身高字段進行驗證。
    if(this.detailConfig.personalInfoConfig.personalInfo){
        this.$refs['personalInfoForm'].validate((valid,failedInfo) => {
            // 我的信息下的年齡、身高字段進行驗證經過。
            if(valid){
                // 判斷地址信息是否啓用,啓用的話須要對地址信息下的城市、省份進行驗證
                if(this.detailConfig.addressInfoConfig.addressInfo){
                   this.$refs['addressInfoForm'].validate((valid,failedInfo) => {
                        // 地址信息下的城市、省份驗證成功。關閉dialog
                        if(valid){
                            this.modelVisible = false;
                        }else{
                            return false;
                        }
                    })
                }else{
                    this.modelVisible = false;
                }
            }else{
                return false;
            }
        })
    // 若是地址信息啓用,則須要對地址信息下的省份、城市字段進行驗證。 
    }else if(this.detailConfig.addressInfoConfig.addressInfo){
        this.$refs['addressInfoForm'].validate((valid,failedInfo) => {
            if(valid){
                this.modelVisible = false;
            }else{
                return false;
            }
        })  
    // 我的信息和地址信息均沒有啓用,直接關閉dialog 
    }else{
        this.modelVisible = false;
    }                    
}
複製代碼

能夠看到這裏有多層嵌套的邏輯判斷。

那這個驗證功能無非就是但願當前不選中那一項就不驗證那一項,那能不能將校驗規則定義爲動態的,不選中時移除校驗規則,選中時添加上校驗規則。

那麼答案是能夠的,因此接下來就來實現一下。

首先咱們在data數據中定義多個規則。

personalInfoConfig:{
    personalInfo: false,
    age: '',
    height: '',
    rules: {
        age: [{
            type: 'number',
            message: '年齡必須爲數字值'
        }],
        height: [{
            type: 'number',
            message: '身高必須爲數字值'
        }]
    },
    // 定義空的驗證規則
    emptyRules: {}
},
addressInfoConfig:{
    addressInfo: false,
    province: '',
    city: '',
    rules: {
        province: [
            { min: 2, max: 10, message: '長度必須在2-10個字符'}
        ],
        city: [
            { min: 2, max: 10, message: '長度必須在2-10個字符' }
        ]
    },
    // 定義空的驗證規則
    emptyRules: {}
}
複製代碼

即一個正常的驗證規則,對應複選框啓用時的驗證;還要一個空的驗證規則,對應複選框取消啓用時的驗證。

而後咱們將規則定義到計算屬性中。

computed:{
    personalInfoRules: function(){
        if(this.detailConfig.personalInfoConfig.personalInfo == true){
            return this.detailConfig.personalInfoConfig.rules;
        }else{
            return this.detailConfig.personalInfoConfig.emptyRules;
        }
    },
    addressInfoRules: function(){
        if(this.detailConfig.addressInfoConfig.addressInfo == true){
            return this.detailConfig.addressInfoConfig.rules;
        }else{
            return this.detailConfig.addressInfoConfig.emptyRules;
        }
    }
},

複製代碼

接着就是將計算屬性綁定到對應表單的rules屬性上。

<!-- 我的信息 -->
<el-form :model="detailConfig.personalInfoConfig" label-width="80px" lable-suffix=":" ref="personalInfoForm" :rules="personalInfoRules">
    <!-- 省略 -->
</el-form>

<!-- 住址信息 -->
<el-form :model="detailConfig.personalInfoConfig" label-width="80px" lable-suffix=":" ref="personalInfoForm" :rules="personalInfoRules">
    <!-- 省略 -->
</el-form>
複製代碼

能夠看到el-form上綁定的rules已經修改成computed中定義的屬性了。

這樣的改動完成以後,最後一步就是重寫校驗邏輯了。

saveConfig(){
    this.$refs['personalInfoForm'].validate((valid,failedInfo) => {
        // 我的信息下的年齡、身高字段進行驗證經過。
        if(valid){   
            this.$refs['addressInfoForm'].validate((valid,failedInfo) => {
                // 地址信息下的城市、省份驗證成功,關閉dialog
                if(valid){
                    this.modelVisible = false;
                }else{
                    return false;
                }
            })   
        }else{
            return false;
        }
    })        
},
複製代碼

由於規則在動態的變化,而驗證的邏輯就不須要複選框的啓用禁用進行判斷,直接使用規則進行驗證便可。因此的驗證邏輯是否是就清爽了不少。

那這個就是針對表單驗證作的一個小小的優化。 若是你們有更好的方法能夠分享給我

bug修復

在功能測試的過程當中,我還發現一個問題。

當我在表單中填寫了錯誤格式的數據後,直接經過點擊彈窗上方的叉號按鈕來關閉dialog(不點擊保存按鈕),那此時detailConfig中的字段值已是那個錯誤格式的數據(雙向數據綁定原理),若是直接將最終的detailConfig發送到後端顯然是不對的。

目前暫時尚未一個好的解決思路,正在思考中,歡迎你們和我交流。

完整代碼

最後我將本次實踐的完整代碼貼在這裏。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Element Form表單實踐</title>
    <!-- 開發環境版本,包含了有幫助的命令行警告 -->
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

    <!-- 引入樣式 -->
    <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
    <!-- 引入組件庫 -->
    <script src="https://unpkg.com/element-ui/lib/index.js"></script>
    
</head>
<body>
    <div id="box">
        <el-form label-suffix=":" :model="form" label-width="80px" ref="form">
            <el-form-item label="名稱" prop="name" :rules="[{ required:true, trigger: 'blur', message: '名稱是必填項' }]">
                <el-input v-model="form.name"></el-input>
            </el-form-item>
            <el-form-item label="選項">
                <el-switch v-model="form.item"></el-switch>
                <el-button :disabled="!form.item" type="primary" size="small" @click="modelVisible=true">詳細配置</el-button>
            </el-form-item>
            <el-form-item>
                <el-button type="primary" size="small" @click="saveInfo">保存</el-button>
            </el-form-item>
        </el-form>   
        
        <!-- 詳細配置 -->
        <el-dialog title="詳細配置" :visible.sync="modelVisible">
            <el-form :model="detailConfig" ref="detailForm">
                <el-form :model="detailConfig.personalInfoConfig" label-width="80px" lable-suffix=":" ref="personalInfoForm" :rules="personalInfoRules">
                    <el-form-item prop="personalInfo">
                        <el-checkbox label="personalInfo" v-model="detailConfig.personalInfoConfig.personalInfo">我的信息</el-checkbox>
                    </el-form-item>
                    <el-form-item label="年齡" prop="age">
                        <el-input v-model.number="detailConfig.personalInfoConfig.age" :disabled="!detailConfig.personalInfoConfig.personalInfo"></el-input>
                    </el-form-item>
                    <el-form-item label="身高" prop="height">
                        <el-input v-model.number="detailConfig.personalInfoConfig.height" :disabled="!detailConfig.personalInfoConfig.personalInfo"></el-input>
                    </el-form-item>
                </el-form>
                <el-form :model="detailConfig.addressInfoConfig" label-width="80px" lable-suffix=":" ref="addressInfoForm" :rules="addressInfoRules">
                    <el-form-item prop="addressInfo">
                        <el-checkbox v-model="detailConfig.addressInfoConfig.addressInfo" label="addressInfo">住址信息</el-checkbox>
                    </el-form-item>
                    <el-form-item label="省份" prop="province">
                        <el-input v-model="detailConfig.addressInfoConfig.province" :disabled="!detailConfig.addressInfoConfig.addressInfo"></el-input>
                    </el-form-item>
                    <el-form-item label="城市" prop="city">
                        <el-input v-model="detailConfig.addressInfoConfig.city" :disabled="!detailConfig.addressInfoConfig.addressInfo"></el-input>
                    </el-form-item>
                </el-form>
                <el-form-item>
                    <el-button type="primary" @click="saveConfig">保存</el-button>
                    <el-button type="primary" @click='resetForm'>重置</el-button>
                </el-form-item>
            </el-form>
        </el-dialog>
    </div>
    <script> var vm = new Vue({ el: '#box', computed:{ personalInfoRules: function(){ if(this.detailConfig.personalInfoConfig.personalInfo == true){ return this.detailConfig.personalInfoConfig.rules; }else{ return this.detailConfig.personalInfoConfig.emptyRules; } }, addressInfoRules: function(){ if(this.detailConfig.addressInfoConfig.addressInfo == true){ return this.detailConfig.addressInfoConfig.rules; }else{ return this.detailConfig.addressInfoConfig.emptyRules; } } }, watch:{ "detailConfig.personalInfoConfig.personalInfo": function(personalInfo){ if(personalInfo == false){ this.$refs['personalInfoForm'].resetFields() } }, "detailConfig.addressInfoConfig.addressInfo": function(addressInfo){ if(addressInfo == false){ this.$refs['addressInfoForm'].resetFields() } } }, data: { form: { name: "", item: false }, modelVisible: false, detailConfig: { personalInfoConfig:{ personalInfo: false, age: '', height: '', rules: { age: [{ type: 'number', message: '年齡必須爲數字值' }], height: [{ type: 'number', message: '身高必須爲數字值' }] }, // 定義空的驗證規則 emptyRules: {} }, addressInfoConfig:{ addressInfo: false, province: '', city: '', rules: { province: [ { min: 2, max: 10, message: '長度必須在2-10個字符'} ], city: [ { min: 2, max: 10, message: '長度必須在2-10個字符' } ] }, // 定義空的驗證規則 emptyRules: {} } } }, methods: { saveInfo() { this.$refs['form'].validate((valid,failedInfo) => { if(valid){ // 將表單數據組合到一塊兒 // 這樣方式比較簡單,不過會將數據中的rules傳遞到後端 let data = { ...this.detailConfig, ...this.form } // 將數據發送到後端 // 代碼省略...... // 數據保存成功提示用戶 this.$message({ message: '保存成功', type: "success", center: true }); }else{ return false; } }) }, saveConfig(){ this.$refs['personalInfoForm'].validate((valid,failedInfo) => { // 我的信息下的年齡、身高字段進行驗證經過。 if(valid){ this.$refs['addressInfoForm'].validate((valid,failedInfo) => { // 地址信息下的城市、省份驗證成功。關閉dialog if(valid){ this.modelVisible = false; }else{ return false; } }) }else{ return false; } }) }, resetForm(formName){ this.$refs['personalInfoForm'].resetFields(); this.$refs['addressInfoForm'].resetFields(); // 調用外層表單的`resetFileds`方法沒有辦法去重置表單內容 // this.$refs['detailForm'].resetFields(); } } }) </script>
</body>
</html>
複製代碼

注意在主頁面保存整個表單內容是,我使用ES6的展開運算符將主頁面的表單數據和彈框組件內的表單數據合併到了一塊兒,這樣就能夠直接將合併後的數據發送到後端。 使用展開運算符合並數據雖然比較方便,可是定義的驗證規則數據也會包含在最終的結果中。

寫在最後

做者實現的這個功能是在一個原本完整的表單提交功能上新增的一個小功能。當時已經完成的表單的數據結構是根據業務和邏輯設計的多層嵌套字典,因此後面我新增的這個數據結構也是嵌套在字典裏層的。

// 這個數據是根據業務邏輯設計的多層嵌套字典
people{
    // 這裏還有別的表單的數據
    
    // config是我新增的表單數據
    config:{
        icmpconfig:{
            time:10
        },
        tcpconfig:{
            time:10
        }
    }
}
複製代碼

可是剛一開始我並無作表單嵌套,而是在外層使用單個的el-form實現。

到後面作驗證添加rules的時候,prop的值就得寫成people.icmpconfig.time,但實際是prop是不能寫成這樣.的形式,寫了以後會報錯說time沒有定義。

介於這個緣由,在綜合前面的說法:

是一整個使用表單嵌套的緣由。

使用表單嵌套感受有利也有弊,方便了一些邏輯,也帶來了一些問題。

因此必定要提早設計好,選擇一個合理的實現方式。

關於

做者

小土豆biubiubiu

一個努力學習的前端小菜鳥,知識是無限的。堅信只要不停下學習的腳步,總能到達本身指望的地方

同時仍是一個喜歡小貓咪的人,家裏有一隻美短小母貓,名叫土豆

博客園

www.cnblogs.com/HouJiao/

掘金

juejin.im/user/58c61b…

微信公衆號

土豆媽的碎碎念

微信公衆號的初衷是記錄本身和身邊的一些故事,同時會不按期更新一些技術文章

歡迎你們掃碼關注,一塊兒吸貓,一塊兒聽故事,一塊兒學習前端技術

做者寄語

小小總結,歡迎你們指導~

相關文章
相關標籤/搜索