1 表單el-form
每個(gè)表單el-form
由多個(gè)表單域el-form-item
組成。默認(rèn)情況笔宿,表單域是垂直分布的,可以設(shè)置el-form
的inline=‘true’
屬性,使表單水平分布限寞,當(dāng)多個(gè)表單域el-form在一行顯示不完時(shí),會(huì)自動(dòng)換行仰坦。
1.1 表單的模型對(duì)象model
el-form使用model屬性來(lái)描述表單的數(shù)據(jù)模型對(duì)象履植,在指定數(shù)據(jù)對(duì)象后,其下的form-item能夠使用該數(shù)據(jù)對(duì)象悄晃,比如引用數(shù)據(jù)對(duì)象的值玫霎,或數(shù)據(jù)驗(yàn)證等。
<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"
指定了表單的模型對(duì)象妈橄,在el-form-item表單域中對(duì)模型對(duì)象的值做了雙向綁定庶近,需要注意的是表單域中v-model='dto.name'
即使沒(méi)有模型對(duì)象,也是能夠正常運(yùn)行的眷蚓。但是鼻种,表單的模型對(duì)象在表單調(diào)用其驗(yàn)證方法validate(見(jiàn)驗(yàn)證規(guī)則一節(jié))時(shí)是必須的。
1.2 表單域的標(biāo)簽
每個(gè)表單域都有一個(gè)標(biāo)簽(不是必選),用el-form-item的label
屬性指定沙热,表單域的標(biāo)簽有位置和寬度兩個(gè)屬性叉钥。
- label-position 表示標(biāo)簽的對(duì)齊方式,它有
right(默認(rèn))|left|top
三個(gè)取值篙贸,該屬性是加在el-form元素上的沼侣,即只能對(duì)其下所有表單域進(jìn)行統(tǒng)一的設(shè)置。 - label-width 表示標(biāo)簽的寬度歉秫,只有當(dāng)label-position為right或left時(shí)有效蛾洛,label-width的值需要帶單位,比如
label-width='120px'
。label-width可以加載el-form元素上轧膘,表示對(duì)其下的所有表單域的標(biāo)簽進(jìn)行統(tǒng)一的設(shè)置钞螟,也可以加載el-form-item元素上,表示對(duì)單個(gè)表單域標(biāo)簽設(shè)置谎碍,el-form-item的優(yōu)先級(jí)高于el-form的優(yōu)先級(jí)鳞滨。 - label-suffix 標(biāo)簽的后綴,該屬性在el-form標(biāo)簽中設(shè)置蟆淀。也就是說(shuō)拯啦,如果設(shè)置了該項(xiàng),其下的所有設(shè)置了標(biāo)簽(label)的表單域熔任,都會(huì)添加后綴褒链。
<!-- 在表單元素上統(tǒng)一設(shè)置了表單域標(biāo)簽元素的位置和寬度 -->
<el-form label-position='left' label-width='100px' :model="dto">
<el-form-item label="名稱(chēng)">
<el-input v-model="dto.name"></el-input>
</el-form-item>
<!-- 單獨(dú)設(shè)置該表單域的標(biāo)簽寬度,優(yōu)先級(jí)高于el-form上設(shè)置的寬度 -->
<el-form-item label="組名稱(chēng)" label-width='120px'>
<el-input v-model="dto.name"></el-input>
</el-form-item>
</el-form>
表單域的label屬性是字符串類(lèi)型的疑苔,如果要用其他類(lèi)型(如圖片)或復(fù)雜的標(biāo)簽樣式甫匹,顯然label是不能滿足的,element為我們提供標(biāo)簽具名插槽惦费,具名插槽的名稱(chēng)為label兵迅。
<el-form-item>
<!--使用具名插槽設(shè)置label-->
<template v-slot:lable>
<img :src="logo" alt="" style="width:16px">
</template>
<el-input v-model="dto.name"></el-input>
</el-form-item>
具名插槽的優(yōu)先級(jí)高于label屬性,同時(shí)薪贫,使用具名插槽后label-suffix屬性設(shè)置的標(biāo)簽后綴也會(huì)失效恍箭。
1.3 表單域的布局
element對(duì)其定義的表單元素做了默認(rèn)的樣式,比如:e-input默認(rèn)是width:100%
瞧省,element會(huì)在input元素的外面包裹一層div扯夭,其渲染后的樣子如下:
<div class="el-input">
<input type="text" class="el-input__inner"/>
</div>
<!--
el-input樣式中width:100%
el-input__inner樣式中width:100%
-->
如上面的分析,如果要修改input的寬度臀突,我們有以下幾種方法:
- 為表單元素el-input添加一個(gè)類(lèi)勉抓,設(shè)置其width
- 復(fù)寫(xiě)生成的div標(biāo)簽的el-input樣式贾漏,設(shè)置其width
- 在表單元素el-input外面設(shè)置一個(gè)外殼候学,為這個(gè)外殼設(shè)置width
我們?yōu)閑l-input組件添加的任何自定義樣式,最后都會(huì)加在外層的div標(biāo)簽上纵散,而webpack渲染出的最終頁(yè)面梳码,是先加載我們自定義的樣式,后加載element的默認(rèn)樣式伍掀。所以掰茶,如果我們?cè)谧远x的樣式中設(shè)置了寬度,會(huì)被默認(rèn)樣式覆蓋掉蜜笤,也就是說(shuō)濒蒋,我們?cè)谧远x樣式中設(shè)置width值是不起作用的,如下:
<template>
<div id="app">
<el-input class="width-200" />
</div>
</template>
<style>
.width-200{
width:200px;
}
</style>
渲染后的結(jié)構(gòu)是
<head>
<style type="text/css">
/*不會(huì)生效*/
.width-200 {
width: 200px;
}
</style>
<style type="text/css">
/*element中的樣式*/
</style>
</head>
<body>
<div class="width-200 el-input">
<input type="text" class="el-input__inner"/>
</div>
</body>
width-200(width:200px)和el-input(width:100%)中都有width屬性,因?yàn)?code><div class="width-200 el-input">中el-input在width-200的后面沪伙,所以瓮顽,width-200中的寬度被覆蓋。
我們可以利用css選擇器優(yōu)先級(jí)高低排列來(lái)處理這個(gè)問(wèn)題围橡,簡(jiǎn)單的說(shuō)暖混,我們將自定義的樣式的權(quán)重設(shè)高,來(lái)解決無(wú)效的問(wèn)題翁授。選擇器的權(quán)重用4個(gè)部分表示(0,0,0,0)拣播,分別表示(行內(nèi)樣式,ID選擇器收擦,類(lèi)/屬性/偽類(lèi)贮配,元素/偽元素),他們的優(yōu)先級(jí)從右到左依次升高炬守,同一個(gè)級(jí)別的的選擇器有幾個(gè)牧嫉,該部分的數(shù)字就是幾,比如:
/* demo1 權(quán)重(0,0,2,1)*/
.class-a .class-b div{
color:red;
}
/* demo2 權(quán)重(0,0,1,3) */
.class-a div ul li{
color:blue;
}
上面的例子中减途,demo1的優(yōu)先級(jí)高于demo2酣藻,因?yàn)樵陬?lèi)這個(gè)級(jí)別demo1高于demo2,所以不管在元素級(jí)別demo2的值怎么高鳍置,優(yōu)先級(jí)也是比不過(guò)demo1辽剧。注意:
- 權(quán)重表示方法沒(méi)有進(jìn)位的說(shuō)法
-
!important
是最高級(jí)別,它高于所有的權(quán)重
對(duì)于el-input我們可以在外面加一層id選擇器税产,如#app .width-200{width:200px}
怕轿,這樣width-200的優(yōu)先級(jí)就高于el-input的優(yōu)先級(jí)。
第2個(gè)解決方案中辟拷,在樣式引入時(shí)(html的head標(biāo)簽中)撞羽,復(fù)寫(xiě)的el-input樣式會(huì)在element的el-input的樣式之前,所以衫冻,element的el-input的樣式會(huì)層疊掉自定義的el-input的樣式诀紊。可以在自定義的el-input樣式的寬度上使用!important
隅俘,強(qiáng)制使用自定義樣式的寬度邻奠,不推薦這種方式。
第3中方案比較好理解为居,在element中碌宴,可以使用柵格布局的方式來(lái)處理表單元素的位置。
2 表單驗(yàn)證
表單驗(yàn)證的對(duì)象是el-form
中model屬性指定的數(shù)據(jù)對(duì)象蒙畴。
21 驗(yàn)證規(guī)則
element的驗(yàn)證規(guī)則使用async-validator贰镣,規(guī)則的部分屬性如下:
屬性名 | 說(shuō)明 |
---|---|
type | 待驗(yàn)證對(duì)象的數(shù)據(jù)類(lèi)型,取值范圍:string(默認(rèn))|number|boolean|method|regexp|integer|float|array|object|enum|date|url|hex|email |
required | 是否為必須 |
pattern | 正則表達(dá)式 |
min | 最小值,string和array類(lèi)型對(duì)比其length屬性碑隆,number類(lèi)型對(duì)比起本身的值 |
max | 最大值董朝,參照值與min相似 |
len | 長(zhǎng)度,參照值與min相似干跛,但是他是進(jìn)準(zhǔn)的表達(dá)子姜,比如驗(yàn)證一個(gè)array對(duì)象的len是3,那么楼入,這個(gè)array的長(zhǎng)度就必須為3才能滿足條件哥捕,如果是number類(lèi)型,表示這個(gè)值必須與len中的值一樣 |
enum | 當(dāng)type:enum時(shí)嘉熊,enum選項(xiàng)才有意義遥赚,它后接數(shù)組集合,驗(yàn)證數(shù)據(jù)是否在此集合中 |
fields | 深度驗(yàn)證阐肤,當(dāng)驗(yàn)證的type為object凫佛,可以驗(yàn)證其內(nèi)部數(shù)據(jù) |
message | 錯(cuò)誤消息,類(lèi)型為字符串或函數(shù) |
validator | 自定驗(yàn)證函數(shù)孕惜,函數(shù)的參數(shù)為(rule,value,callback) |
在element中愧薛,將規(guī)則封裝到一個(gè)規(guī)則對(duì)象中,規(guī)則對(duì)象的鍵(規(guī)則名)要與模型對(duì)象的鍵一致衫画。鍵的值就是具體的規(guī)則毫炉,它可以是一個(gè)對(duì)象包含規(guī)則的屬性和值,也可以是一個(gè)數(shù)組對(duì)象包含多條規(guī)則削罩。
規(guī)則對(duì)象與模型對(duì)象一樣瞄勾,由表單元素el-form
引用,使用rules
屬性指定(模型對(duì)象由model
屬性指定)弥激。有了對(duì)規(guī)則對(duì)象的引用进陡,還需要在具體的表單域中指定使用那一條規(guī)則,在el-form-item
表單域中使用prop
指定規(guī)則名微服。
<template>
<div id="app">
<!--
使用model指定模型對(duì)象趾疚,使用rules指定規(guī)則對(duì)象
模型對(duì)象就是規(guī)則要驗(yàn)證的數(shù)據(jù)對(duì)象
-->
<el-form ref="validateForm" :model="dto" :rules="rules" label-width="80px">
<!-- 在表單域中使用prop屬性指定規(guī)則對(duì)象中的規(guī)則名 -->
<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>
</div>
</template>
<script>
export default {
data() {
return {
dto: { name: "張三", groupName: "管理組" },
//規(guī)則對(duì)象定義,鍵為對(duì)象名职辨,建議與數(shù)據(jù)對(duì)象的鍵相同盗蟆,
//值為規(guī)則戈二,可以是單條規(guī)則舒裤,也可以是集合
rules: {
// trigger是element中自定義的屬性,見(jiàn)觸發(fā)驗(yàn)證一節(jié)
name: { required: true, message: "名稱(chēng)為必填項(xiàng)", trigger: "blur" },
groupName: [
//gorupName有多條規(guī)則觉吭,不同的規(guī)則驗(yàn)證不同的方面
{ required: true, message: "組名為必填", trigger: "blur" },
{ min: 3, max: 16, message: "組名長(zhǎng)度在3-16之間", trigger: "blur" },
{ pattern: /^\w+$/, message: "不能包含特殊字符", trigger: "blur" }
]
}
};
},
};
</script>
2.2 觸發(fā)驗(yàn)證
element在驗(yàn)證規(guī)則中加入了自動(dòng)觸發(fā)條件trggier
屬性腾供,目前它的取值為blur
和change(默認(rèn))
兩項(xiàng),表示當(dāng)表單元素失去焦點(diǎn),或內(nèi)容改變時(shí)觸發(fā)該項(xiàng)驗(yàn)證伴鳖。注意节值,它們也可以組合使用,如:trigger:['blur','change']
榜聂。
我們也可以通過(guò)el-form的實(shí)例方法validate
手動(dòng)觸發(fā)整個(gè)表單的驗(yàn)證搞疗,或者使用實(shí)例方法validateField
指定部分字段做驗(yàn)證。這里提到了實(shí)例方法须肆,也就是說(shuō)我們要得到el-form的實(shí)例匿乃,一般使用vue的ref屬性定義這個(gè)對(duì)象的引用名。
validateForm() {
//通過(guò)refs獲取表單的引用
let { form } = this.$refs;
//調(diào)用表單的實(shí)例方法validate做全部驗(yàn)證
//該方法的參數(shù)為一個(gè)回調(diào)函數(shù)
//回調(diào)函數(shù)有兩個(gè)可選參數(shù)豌汇,一個(gè)表示是否驗(yàn)證通過(guò)幢炸,第二個(gè)是未通過(guò)的字段集合
form.validate((result,errorFields)=>{
console.log(result);
console.log(errObject);
})
},
validateFields(){
//通過(guò)refs獲取表單的引用
let { form } = this.$refs;
//調(diào)用表單的實(shí)例方法validateField做指定字段的驗(yàn)證
//該方法的有兩個(gè)參數(shù),第一個(gè)為要驗(yàn)證的字段拒贱,如果是當(dāng)用string宛徊,多個(gè)用array類(lèi)型
//第二個(gè)參數(shù)為回調(diào)函數(shù),該函數(shù)只有一個(gè)string類(lèi)型的參數(shù)逻澳,表示錯(cuò)誤信息
form.validateField(['name','groupName'],error=>{
console.log(error);
})
}
注意:使用validateField
方法驗(yàn)證多個(gè)字段時(shí)闸天,每驗(yàn)證一次,都會(huì)調(diào)用回調(diào)函數(shù)一次斜做,通過(guò)驗(yàn)證的字段會(huì)error==''
号枕,沒(méi)通過(guò)驗(yàn)證的字段,返回對(duì)應(yīng)規(guī)則的message錯(cuò)誤消息字段陨享。
3 案例
有時(shí)候需要對(duì)字段做動(dòng)態(tài)的驗(yàn)證葱淳,可以為表單域的prop動(dòng)態(tài)綁定規(guī)則。比如:有一個(gè)select選擇器表示字段的輸入類(lèi)型抛姑,有文本赞厕、單選兩種。當(dāng)為文本時(shí)定硝,可以填寫(xiě)文本的默認(rèn)值(非必須)皿桑,當(dāng)為單選時(shí),要填寫(xiě)單選的取值范圍(必須)蔬啡。
需求:
字段類(lèi)型:
文本:填寫(xiě)默認(rèn)值诲侮,非必須
單選:填寫(xiě)選項(xiàng),多個(gè)選項(xiàng)使用','分隔
代碼實(shí)現(xiàn):
<template>
<div id="app">
<el-form ref="form" :model="dto" :rules="rules" label-width="80px">
<el-form-item label="輸入類(lèi)型">
<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的值改變時(shí)箱蟆,要重新渲染el-form-item元素沟绪,
但是vue出于性能的考慮,會(huì)復(fù)用之前的el-form-item元素空猜,
添加key屬性可以強(qiáng)制使用新的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>
</div>
</template>
<script>
const inputType = [{ value: 0, label: "文本" }, { value: 1, label: "單選" }];
const rules = {
inputValue: [
{ required: true, message: "字段值為必填", trigger: "blur" },
{
//使用正則表達(dá)式做逗號(hào)驗(yàn)證
pattern: /^([\u0391-\uFFE5\d\w,])*([\u0391-\uFFE5\d\w]+)$/g,
message: "選項(xiàng)需要用','號(hào)隔開(kāi)",
trigger: "blur"
}
]
};
export default {
data() {
return {
inputType,
rules,
dto: {
type: 0,
inputValue: ""
}
};
},
computed:{
inputValueRule(){
//當(dāng)輸入類(lèi)型類(lèi)單選時(shí)绽慈,返回規(guī)則指定的規(guī)則名稱(chēng)
return this.dto.type==1?"inputValue":"";
}
}
};
</script>