1 表单el-form
每个表单
el-form
由多个表单域
el-form-item
组成。默认情况,表单域是垂直分布的,可以设置
el-form
的
inline=‘true’
属性,使表单水平分布,当多个表单域el-form在一行显示不完时,会自动换行。
1.1 表单的模型对象model
el-form使用model属性来描述表单的数据模型对象,在指定数据对象后,其下的form-item能够使用该数据对象,比如引用数据对象的值,或数据验证等。
<el-form :model="dto">
<el-form-item label="名字">
<el-input v-model="dto.name"></el-input>
</el-form-item>
</el-form>
<script>
export default{
data(){
return {
dto:{name:"张三"},
</script>
上面的代码:model="dto"
指定了表单的模型对象,在el-form-item表单域中对模型对象的值做了双向绑定,需要注意的是表单域中v-model='dto.name'
即使没有模型对象,也是能够正常运行的。但是,表单的模型对象在表单调用其验证方法validate(见验证规则一节)时是必须的。
1.2 表单域的标签
每个表单域都有一个标签(不是必选),用el-form-item的label
属性指定,表单域的标签有位置和宽度两个属性。
label-position 表示标签的对齐方式,它有right(默认)|left|top
三个取值,该属性是加在el-form元素上的,即只能对其下所有表单域进行统一的设置。
label-width 表示标签的宽度,只有当label-position为right或left时有效,label-width的值需要带单位,比如label-width='120px'
。label-width可以加载el-form元素上,表示对其下的所有表单域的标签进行统一的设置,也可以加载el-form-item元素上,表示对单个表单域标签设置,el-form-item的优先级高于el-form的优先级。
label-suffix 标签的后缀,该属性在el-form标签中设置。也就是说,如果设置了该项,其下的所有设置了标签(label)的表单域,都会添加后缀。
<!-- 在表单元素上统一设置了表单域标签元素的位置和宽度 -->
<el-form label-position='left' label-width='100px' :model="dto">
<el-form-item label="名称">
<el-input v-model="dto.name"></el-input>
</el-form-item>
<!-- 单独设置该表单域的标签宽度,优先级高于el-form上设置的宽度 -->
<el-form-item label="组名称" label-width='120px'>
<el-input v-model="dto.name"></el-input>
</el-form-item>
</el-form>
表单域的label属性是字符串类型的,如果要用其他类型(如图片)或复杂的标签样式,显然label是不能满足的,element为我们提供标签具名插槽,具名插槽的名称为label。
<el-form-item>
<!--使用具名插槽设置label-->
<template v-slot:lable>
<img :src="logo" alt="" style="width:16px">
</template>
<el-input v-model="dto.name"></el-input>
</el-form-item>
具名插槽的优先级高于label属性,同时,使用具名插槽后label-suffix属性设置的标签后缀也会失效。
1.3 表单域的布局
element对其定义的表单元素做了默认的样式,比如:e-input默认是width:100%
,element会在input元素的外面包裹一层div,其渲染后的样子如下:
<div class="el-input">
<input type="text" class="el-input__inner"/>
el-input样式中width:100%
el-input__inner样式中width:100%
如上面的分析,如果要修改input的宽度,我们有以下几种方法:
为表单元素el-input添加一个类,设置其width
复写生成的div标签的el-input样式,设置其width
在表单元素el-input外面设置一个外壳,为这个外壳设置width
我们为el-input组件添加的任何自定义样式,最后都会加在外层的div标签上,而webpack渲染出的最终页面,是先加载我们自定义的样式,后加载element的默认样式。所以,如果我们在自定义的样式中设置了宽度,会被默认样式覆盖掉,也就是说,我们在自定义样式中设置width值是不起作用的,如下:
<template>
<div id="app">
<el-input class="width-200" />
</template>
<style>
.width-200{
width:200px;
</style>
渲染后的结构是
<style type="text/css">
/*不会生效*/
.width-200 {
width: 200px;
</style>
<style type="text/css">
/*element中的样式*/
</style>
</head>
<div class="width-200 el-input">
<input type="text" class="el-input__inner"/>
</body>
width-200(width:200px)和el-input(width:100%)中都有width属性,因为<div class="width-200 el-input">
中el-input在width-200的后面,所以,width-200中的宽度被覆盖。
我们可以利用css选择器优先级高低排列来处理这个问题,简单的说,我们将自定义的样式的权重设高,来解决无效的问题。选择器的权重用4个部分表示(0,0,0,0),分别表示(行内样式,ID选择器,类/属性/伪类,元素/伪元素),他们的优先级从右到左依次升高,同一个级别的的选择器有几个,该部分的数字就是几,比如:
/* demo1 权重(0,0,2,1)*/
.class-a .class-b div{
color:red;
/* demo2 权重(0,0,1,3) */
.class-a div ul li{
color:blue;
上面的例子中,demo1的优先级高于demo2,因为在类这个级别demo1高于demo2,所以不管在元素级别demo2的值怎么高,优先级也是比不过demo1。注意:
权重表示方法没有进位的说法
!important
是最高级别,它高于所有的权重
对于el-input我们可以在外面加一层id选择器,如#app .width-200{width:200px}
,这样width-200的优先级就高于el-input的优先级。
第2个解决方案中,在样式引入时(html的head标签中),复写的el-input样式会在element的el-input的样式之前,所以,element的el-input的样式会层叠掉自定义的el-input的样式。可以在自定义的el-input样式的宽度上使用!important
,强制使用自定义样式的宽度,不推荐这种方式。
第3中方案比较好理解,在element中,可以使用栅格布局的方式来处理表单元素的位置。
2 表单验证
表单验证的对象是el-form
中model属性指定的数据对象。
21 验证规则
element的验证规则使用async-validator,规则的部分属性如下:
待验证对象的数据类型,取值范围:string(默认)|number|boolean|method|regexp|integer|float|array|object|enum|date|url|hex|email
required
是否为必须
pattern
正则表达式
最小值,string和array类型对比其length属性,number类型对比起本身的值
最大值,参照值与min相似
长度,参照值与min相似,但是他是进准的表达,比如验证一个array对象的len是3,那么,这个array的长度就必须为3才能满足条件,如果是number类型,表示这个值必须与len中的值一样
当type:enum时,enum选项才有意义,它后接数组集合,验证数据是否在此集合中
fields
深度验证,当验证的type为object,可以验证其内部数据
message
错误消息,类型为字符串或函数
validator
自定验证函数,函数的参数为(rule,value,callback)
在element中,将规则封装到一个规则对象中,规则对象的键(规则名)要与模型对象的键一致。键的值就是具体的规则,它可以是一个对象包含规则的属性和值,也可以是一个数组对象包含多条规则。
规则对象与模型对象一样,由表单元素el-form
引用,使用rules
属性指定(模型对象由model
属性指定)。有了对规则对象的引用,还需要在具体的表单域中指定使用那一条规则,在el-form-item
表单域中使用prop
指定规则名。
<template>
<div id="app">
使用model指定模型对象,使用rules指定规则对象
模型对象就是规则要验证的数据对象
<el-form ref="validateForm" :model="dto" :rules="rules" label-width="80px">
<!-- 在表单域中使用prop属性指定规则对象中的规则名 -->
<el-form-item label="名字" prop="name">
<el-input v-model="dto.name"></el-input>
</el-form-item>
<el-form-item label="组名字" prop="groupName">
<el-input v-model="dto.groupName" />
</el-form-item>
</el-form>
</template>
<script>
export default {
data() {
return {
dto: { name: "张三", groupName: "管理组" },
//规则对象定义,键为对象名,建议与数据对象的键相同,
//值为规则,可以是单条规则,也可以是集合
rules: {
// trigger是element中自定义的属性,见触发验证一节
name: { required: true, message: "名称为必填项", trigger: "blur" },
groupName: [
//gorupName有多条规则,不同的规则验证不同的方面
{ required: true, message: "组名为必填", trigger: "blur" },
{ min: 3, max: 16, message: "组名长度在3-16之间", trigger: "blur" },
{ pattern: /^\w+$/, message: "不能包含特殊字符", trigger: "blur" }
</script>
2.2 触发验证
element在验证规则中加入了自动触发条件trggier
属性,目前它的取值为blur
和change(默认)
两项,表示当表单元素失去焦点,或内容改变时触发该项验证。注意,它们也可以组合使用,如:trigger:['blur','change']
。
我们也可以通过el-form的实例方法validate
手动触发整个表单的验证,或者使用实例方法validateField
指定部分字段做验证。这里提到了实例方法,也就是说我们要得到el-form的实例,一般使用vue的ref属性定义这个对象的引用名。
validateForm() {
//通过refs获取表单的引用
let { form } = this.$refs;
//调用表单的实例方法validate做全部验证
//该方法的参数为一个回调函数
//回调函数有两个可选参数,一个表示是否验证通过,第二个是未通过的字段集合
form.validate((result,errorFields)=>{
console.log(result);
console.log(errObject);
validateFields(){
//通过refs获取表单的引用
let { form } = this.$refs;
//调用表单的实例方法validateField做指定字段的验证
//该方法的有两个参数,第一个为要验证的字段,如果是当用string,多个用array类型
//第二个参数为回调函数,该函数只有一个string类型的参数,表示错误信息
form.validateField(['name','groupName'],error=>{
console.log(error);
注意:使用validateField
方法验证多个字段时,每验证一次,都会调用回调函数一次,通过验证的字段会error==''
,没通过验证的字段,返回对应规则的message错误消息字段。
有时候需要对字段做动态的验证,可以为表单域的prop动态绑定规则。比如:有一个select选择器表示字段的输入类型,有文本、单选两种。当为文本时,可以填写文本的默认值(非必须),当为单选时,要填写单选的取值范围(必须)。
字段类型:
文本:填写默认值,非必须
单选:填写选项,多个选项使用','分隔
代码实现:
<template>
<div id="app">
<el-form ref="form" :model="dto" :rules="rules" label-width="80px">
<el-form-item label="输入类型">
<el-select v-model="dto.type">
<el-option
v-for="(item,index) in inputType"
:key="'inputType'+index"
:value="item.value"
:label="item.label"
></el-option>
</el-select>
</el-form-item>
prop的值改变时,要重新渲染el-form-item元素,
但是vue出于性能的考虑,会复用之前的el-form-item元素,
添加key属性可以强制使用新的el-form-item元素
<el-form-item :key="'key'+inputValueRule" label="字段值" :prop="inputValueRule">
<el-input v-model="dto.inputValue"></el-input>
</el-form-item>
</el-form>
</template>
<script>
const inputType = [{ value: 0, label: "文本" }, { value: 1, label: "单选" }];
const rules = {
inputValue: [
{ required: true, message: "字段值为必填", trigger: "blur" },
//使用正则表达式做逗号验证
pattern: /^([\u0391-\uFFE5\d\w,])*([\u0391-\uFFE5\d\w]+)$/g,
message: "选项需要用','号隔开",
trigger: "blur"
export default {
data() {
return {
inputType,
rules,
dto: {
type: 0,
inputValue: ""
computed:{
inputValueRule(){
//当输入类型类单选时,返回规则指定的规则名称
return this.dto.type==1?"inputValue":"";