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…

微信公众号

土豆妈的碎碎念

微信公众号的初衷是记录本身和身边的一些故事,同时会不按期更新一些技术文章

欢迎你们扫码关注,一块儿吸猫,一块儿听故事,一块儿学习前端技术

做者寄语

小小总结,欢迎你们指导~

相关文章
相关标签/搜索