作者:小土豆biubiubiu

博客园:https://www.cnblogs.com/HouJiao/

掘金:https://juejin.im/user/58c61b4361ff4b005d9e894d

微信公众号:土豆妈的碎碎念(扫码关注,一起吸猫,一起听故事,一起学习前端技术)

码字不易,点赞鼓励哟~

前言

上一篇文章 Element Form表单实践(上)参照着文档将表单部分内容实践了一下。

这篇文章将分享项目开发中的一个表单实践,最终做出来的效果大致是下面这个样子:

这个表单看似是比较简单的,但实际上比一般表单存在一些细节的东西需要设计和处理。

接下来就来完成这个功能。

主页面

首先是主页面的实现。

主页面的逻辑非常简单,直接将代码贴出来。

<!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

一个努力学习的前端小菜鸟,知识是无限的。坚信只要不停下学习的脚步,总能到达自己期望的地方

同时还是一个喜欢小猫咪的人,家里有一只美短小母猫,名叫土豆

博客园

https://www.cnblogs.com/HouJiao/

掘金

https://juejin.im/user/58c61b4361ff4b005d9e894d

微信公众号

土豆妈的碎碎念

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

欢迎大家扫码关注,一起吸猫,一起听故事,一起学习前端技术

作者寄语

小小总结,欢迎大家指导~

Element Form表单实践(下)的更多相关文章

  1. Element Form表单实践(上)

    作者:小土豆biubiubiu 博客园:https://www.cnblogs.com/HouJiao/ 掘金:https://juejin.im/user/58c61b4361ff4b005d9e8 ...

  2. Element form表单方法resetFields无效

    之前遇到resetFields无效时都是自己手动用this.ruleForm = Object.assign({}, this.ruleForm, this.$options.data().ruleF ...

  3. 深入了解Element Form表单动态验证问题 转载

    随风丶逆风 2020-04-03 15:36:41  2208  收藏 3 分类专栏: Vue 随笔 文章标签: 动态验证 el-form elementUI 表单验证 版权 在上一篇<vue ...

  4. form表单传递下拉框的Value和Text值,不适用Jquery传递

    同时获取下拉框的Value和Text值的解决办法:添加一个<input type="text" >文本框,用户选中一项后就将该项的value值给他 然后接受页面获取该文 ...

  5. Vue Element Form表单时间验证控件使用

    如果直接使用Element做时间选择器,其规则(rules)不添加type:'date',会提示类型错误,处理这个需要规范值的类型为date. 时间格式化过滤器 import Vue from 'vu ...

  6. 会话保持及Form表单

    1,cookie技术视图views里面:def index(request): #获取请求中的cookie num = request.COOKIES.get('num') if num: num = ...

  7. 基于Bootstrap+jQuery.validate Form表单验证实践

    基于Bootstrap jQuery.validate Form表单验证实践 项目结构 :     github 上源码地址:https://github.com/starzou/front-end- ...

  8. form表单那点事儿(下) 进阶篇

    form表单那点事儿(下) 进阶篇 上一篇主要温习了一下form表单的属性和表单元素,这一片主要讲解用JavaScript如何操作form. 目录: 表单操作 取值 赋值 重置 校验 提交 技巧 不提 ...

  9. 按下回车默认提交form表单问题

    最近开发中碰到一个问题,项目中有几个列表展示页面,允许用户通过查询条件模糊查询数据.用户录入关键字后点击回车会调用查询方法根据关键字查询,原先功能没有问题,但是最近发现在查询输入框中按下回车会直接刷新 ...

随机推荐

  1. zabbix tigger 设置

    设置一个内存在10分钟内持续低于某值才告警: 设置方法: 修改模板的tigger   configuration - > Template OS linux Active(选择自己的模板)-&g ...

  2. 给springboot增加XSS跨站脚本攻击防护功能

    XSS原理 xss攻击的原理是利用前后端校验不严格,用户将攻击代码植入到数据中提交到了后台,当这些数据在网页上被其他用户查看的时候触发攻击 举例:用户提交表单时把地址写成:山东省济南市<scri ...

  3. MES系统介绍(一)

    由于本人从事的行业主要为Mes行业,所以这里准备介绍一下Mes系统的基础概念和实际运用,并且以自己做过的一个实际案例(包括代码)来详细描述自己对Mes系统的认识,帮助小白扫盲,望大神勿喷. MES系统 ...

  4. 2020牛客寒假算法基础集训营2 J题可以回顾回顾

    2020牛客寒假算法基础集训营2 A.做游戏 这是个签到题. #include <cstdio> #include <cstdlib> #include <cstring ...

  5. W - Doom HDU - 5239 线段树 找取模的规律+求一个很大的数的平方对一个数取模的写法 特别的模数==2^63-2^31

    这个题目一开始感觉还是有点难的,这个模数这么大,根本就不知道怎么写,然后去搜了题解,知道了怎么去求当x很大的时候x的平方对一个数取模怎么样不会爆掉. 然后还顺便发现了一个规律就是当一个数更新一定次数之 ...

  6. Java 经典面试题:聊一聊 JUC 下的 LinkedBlockingQueue

    本文聊一下 JUC 下的 LinkedBlockingQueue 队列,先说说 LinkedBlockingQueue 队列的特点,然后再从源码的角度聊一聊 LinkedBlockingQueue 的 ...

  7. 201771010113 李婷华 《面向对象程序设计(Java)》第十六周总结

    一.理论知识部分 1.程序是一段静态的代码,它应用程序执行蓝 是一段静态的代码,它应用程序执行蓝 是一段静态的代码,它应用程序执行蓝本. 2.进程是程序的一次动态执行,它对应了从代码加载.执行至执行完 ...

  8. 【Spark】RDD的依赖关系和缓存相关知识点

    文章目录 RDD的依赖关系 宽依赖 窄依赖 血统 RDD缓存 概述 缓存方式 RDD的依赖关系 RDD和它依赖的父RDD的关系有两种不同的类型,即窄依赖(narrow dependency) 和宽依赖 ...

  9. 【Scala】什么是隐式转换?它又能用来干嘛?该怎么用

    文章目录 定义 隐式参数 隐式转换 隐式值:给方法提供参数 隐式视图 将Int和Double类型转换为String 狗狗学技能(使用别的类中的方法) 使用规则 定义 隐式参数 隐式参数指在函数或者方法 ...

  10. docker-compose安装rabbitmq集群(主从集群---》镜像集群)

    docker-compose安装rabbitmq集群(主从集群--->镜像集群) yls 2020/5/11 创建docker-compose.yml 文件 version: '3' servi ...