vue和iview結(jié)合動(dòng)態(tài)生成表單實(shí)例
在項(xiàng)目中,表單作為用戶輸入占用很重要的一部分,目前的前端框架,基本對(duì)表單進(jìn)行了一些簡(jiǎn)單的封裝,如果輸入項(xiàng)很多,以iview為例,會(huì)有一大堆的類似:
<FormItem label="Input"> ? ? ? ? ? ? <Input v-model="formItem.input" placeholder="Enter something..."></Input></FormItem>
這樣的標(biāo)簽,現(xiàn)在將用
{//input輸入框 type:'InputNumber', placeholder:"請(qǐng)數(shù)量", label:'數(shù)量', value:1, props:'num', isRequire:true, emptyTip:'數(shù)量不能為空' },
這樣的輸入來(lái)簡(jiǎn)化,配置表單的生成。
一、構(gòu)建myform組建
新建myForm.vue文件
1、結(jié)合vue和iveiw的框架,根據(jù)需求,對(duì)表單分一列,兩列,多列展示,需要設(shè)置變量cols,表單項(xiàng)前面的文字寬度也不一樣,因此還需設(shè)置變量labelWidth,渲染表單(展示你想展示的內(nèi)容),需設(shè)置變量formDatas,最后,用戶完成輸入后還需獲取表單數(shù)據(jù),需要設(shè)置變了formDataModel。到此,配置表單大致需要的變量已基本設(shè)置完成。
大致代碼如下:
<Form ref="formValidate" :label-width="labelWidth" :model="formDataModel" class="leftLabel"> ? ? <Row :gutter="32"> ? ? ? <Col :span="cols" v-for="(item,index) in formDatas" :key="index"> ? ? ? ? <myFormItem ?:schema = "item" :key="index" :formObj="formDatas"></myFormItem> ? ? ? </Col> ? ? </Row> </Form>
2、一般情況下每個(gè)表單的下面都會(huì)有操作,比如確定,取消等,這樣我們可以用slot插入來(lái)實(shí)現(xiàn)不同引用頁(yè)面的功能
<section> ? ? ? <slot name="btnCancel" :cancelFormBtn="cancelForm"><Button type="default">取消</Button></slot> ? ? ? <slot name="btnSave" :saveFormBtn="saveForm"><Button type="primary">確定</Button></slot> </section>
這樣myform組件就大致完成,在上面的myform組建中,有一個(gè)myFormItem 的組建,下面我們就來(lái)實(shí)現(xiàn)myFormItem。
二、構(gòu)建myFormItem組建
新建myFormItem.vue文件
myFormItem中,由于表單項(xiàng)有很多種,包括input,select,checkBox等,如果在這個(gè)組建中用v-if來(lái)控制顯示,這樣這個(gè)頁(yè)面很臃腫,因此,采用函數(shù)式組建來(lái)和render函數(shù)來(lái)動(dòng)態(tài)構(gòu)建不同類型的表單
因此myFormItem組建代碼大致如下:
<my-contrl :schema="schema" :formObj="formObj"></my-contrl>
三、構(gòu)建函數(shù)式組件mycontrl組件
新建myContrl.js文件
函數(shù)式組件的大致結(jié)構(gòu)如下,首先根據(jù)context中的類型進(jìn)行分發(fā),然后再用渲染函數(shù)渲染出來(lái)
function getControl(context){ ?? ?let {type,label,placeholder,value} = context.props.shema; ?? ?return {type,label,placeholder,value} } export default{ ?? ?functional:true, ?? ?props:{ ?? ?schema:Object ?? ?}, ?? ?render(h,context){ ?? ??? ?let {type,label,placeholder,value} = getControl(context); ?? ? ? ?return h('FormItem',{ ?? ? ? ??? ??? ? props:{ ? ? ? ? ?? ??? ??? ?label:label, ? ? ? ?? ??? ??? ??? ?}, ?? ? ? ? ? },[ ?? ? ? ??? ?h(type,{ ?? ? ? ??? ?placeholder:placeholder, ? ? ??? ??? ?value:value, ?? ? ? ??? ?}) ?? ? ? ?]) ?? ?} }
中間需注意的小細(xì)節(jié):
1、由于一般設(shè)置必填項(xiàng)和非必填項(xiàng)的樣式不一致,如果要用到iview里面的樣式,需要在formItem下加class:‘ivu-form-item-required’,代碼如下:
class:{ ? ? ? ? 'ivu-form-item-required':isRequire, ? ? ? },
2、如果表單項(xiàng)是select,checkBox等,在select下面會(huì)有option屬性,因?yàn)槎际莿?dòng)態(tài)輸入的值,所以,要用render函數(shù)動(dòng)態(tài)生成數(shù)組
keyValue.map(item=>{ ? ? ? ? return h(keyData,{ ? ? ? ? ? props:{ ? ? ? ? ? ?[keyData==='Option'?'value':keyData==='Button'?'icon':'label']:item.key, ? ? ? ? ? } ? ? ? ? },item.label) ? ? ? })
到此,靜態(tài)頁(yè)面的渲染也就完成了。
四、用戶輸入的時(shí)候需要對(duì)表單項(xiàng)中進(jìn)行各種驗(yàn)證或者邏輯
為了實(shí)現(xiàn)此功能,一般我們用到vue中的混入,將公用的驗(yàn)證,邏輯寫到同一個(gè)文件中,再將每個(gè)表單中單獨(dú)的邏輯放到引用這個(gè)表單的vue中。
因此在mycontrl.js文件的render函數(shù)中,要為每個(gè)表單項(xiàng)注冊(cè)一個(gè)on-change或on-blur事件,然后觸發(fā)對(duì)應(yīng)的函數(shù),并且設(shè)置此表單的對(duì)象的值。
1、設(shè)置表單項(xiàng)的值
context.parent.setValue(context.data.attrs.formObj,props,val);
2、判斷是否必填進(jìn)行操作
if(val==='' || val===null || val.length===0){ ? ? context.parent.Validate('rule-empty',`${label}id`,emptyTip); ? ? ?return; ? ?}else{ ? ? ?context.parent.ValidateHide('rule-empty',`${label}id`) }
3、規(guī)則驗(yàn)證判斷
for(let r = 0;r<rules.length;r++){ ?let flag = rules[r].valide(val); ? if(flag){ ? ?context.parent.ValidateHide(`rule-${rules[r].name}`,`${label}id`) ? ? }else{ ? ? context.parent.Validate(`rule-${rules[r].name}`,`${label}id`,rules[r].tip); ? ? ?break; ? ?} ? } ?return;
4、邏輯判斷
logicRelation(val)
像類似前面的Validate,ValidateHide,setValue這些函數(shù),都放在混入的js函數(shù)中,作為公共函數(shù),而邏輯,規(guī)則下的驗(yàn)證函數(shù)就放在了每個(gè)配置表單的配置項(xiàng)里面了。以上所有的判斷都寫作on-blur或on-change中
五、表單輸入完成獲取表單中的值
這個(gè)寫在myForm.vue中
1、在計(jì)算屬性中,取得這個(gè)表單的項(xiàng)和值
computed:{ ?? ?formDataModel:function(){ ?? ?return this.getValue(this.formDatas); ? ? ? } ? ?}
2、點(diǎn)擊確定按鈕的時(shí)候,將這個(gè)值返回到傳入確定按鈕的這個(gè)函數(shù)中
?? ?saveForm(fn,errFn){ ? ? ? ? let _this = this; ? ? ? ? if(_this.isValidData(_this.formDatas,_this.formDataModel)){ ? ? ? ? ? fn(_this.formDataModel) ? ? ? ? }else{ ? ? ? ? ? _this.$Message.error('表單輸入有誤!請(qǐng)按頁(yè)面提示輸入') ? ? ? ? ? if(errFn){ ? ? ? ? ? ? errFn() ? ? ? ? ? } ? ? ? ? } ? ? ? }
3、取消按鈕,將值還原,或者是別的需要的操作
cancelForm(type,fn){ ? if(type==='modify'){ ? ? fn() ?}else if(type==='close'){ ?this.$emit('closeModel') ? }else{ ? ?this.backDefault(this.defaultValCopy,this.formDatas); ? } }
六、在要用到表單的頁(yè)面使用
?? ??? ?<my-form :formData="formDatas" :cols="12" :labelWidth="100"> ? ? ? ? ? ? <template v-slot:btnCancel ="{cancelFormBtn}"> ? ? ? ? ? ? ? <Button type="default" @click="cancelFormBtn('modify',getlist)">取消</Button> ? ? ? ? ? ? </template> ? ? ? ? ? ? <template v-slot:btnSave ="{saveFormBtn}" > ? ? ? ? ? ? ? <Button type="primary" @click="saveFormBtn(save)">保存</Button> ? ? ? ? ? ? </template> ? ? ? ? ?</my-form>
配置項(xiàng)中的formData格式
? ? ? ?[ { ? ? ? ? ? ? type:'InputNumber', ? ? ? ? ? ? placeholder:"Web", ? ? ? ? ? ? label:'Web', ? ? ? ? ? ? value:1, ? ? ? ? ? ? props:'web', ? ? ? ? ? ? isRequire:true, ? ? ? ? ? ? emptyTip:'Web不為空' ? ? ? ? ? }, ? ? ? ? ? {//select選擇框 ? ? ? ? ? ? type:'Select', ? ? ? ? ? ? placeholder:"請(qǐng)選擇要輸入內(nèi)容", ? ? ? ? ? ? label:'記錄', ? ? ? ? ? ? data:{ ? ? ? ? ? ? ? Option:[ ? ? ? ? ? ? ? {key:'1',label:'記錄'}, ? ? ? ? ? ? ? {key:'0',label:'不記錄'}, ? ? ? ? ? ? ] ? ? ? ? ? ? }, ? ? ? ? ? ? value:'1', ? ? ? ? ? ? props:'record', ? ? ? ? ? ? isRequire:true, ? ? ? ? ? ? emptyTip:'請(qǐng)選擇', ? ? ? ? ? ? logicRelation:this.isHideKafka ? ? ? ? ? }]
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
實(shí)現(xiàn)Vue的markdown文檔可以在線運(yùn)行的方法示例
這篇文章主要介紹了實(shí)現(xiàn)Vue的markdown文檔可以在線運(yùn)行的方法示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-12-12vue中Npm run build 根據(jù)環(huán)境傳遞參數(shù)方法來(lái)打包不同域名
這篇文章主要介紹了vue項(xiàng)目中Npm run build 根據(jù)環(huán)境傳遞參數(shù)方法來(lái)打包不同域名,使用npm run build --xxx,根據(jù)傳遞參數(shù)xxx來(lái)判定不同的環(huán)境,給出不同的域名配置,具體內(nèi)容詳情大家參考下本文2018-03-03詳解如何在Vue項(xiàng)目中發(fā)送jsonp請(qǐng)求
這篇文章主要介紹了詳解如何在Vue項(xiàng)目中發(fā)送jsonp請(qǐng)求,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10Vue.js實(shí)戰(zhàn)之組件的進(jìn)階
組件(Component)是 Vue.js 最強(qiáng)大的功能之一,之前的文章都只是用到了基本的封裝功能,這次將介紹一些更強(qiáng)大的擴(kuò)展。這篇文章主要介紹了Vue.js實(shí)戰(zhàn)之組件進(jìn)階的相關(guān)資料,需要的朋友們可以參考借鑒,下面來(lái)一起看看吧。2017-04-04vue-cli 自定義指令directive 添加驗(yàn)證滑塊示例
本篇文章主要介紹了vue-cli 自定義指令directive 添加驗(yàn)證滑塊示例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-10-10vuejs前后端數(shù)據(jù)交互之從后端請(qǐng)求數(shù)據(jù)的實(shí)例
今天小編就為大家分享一篇vuejs前后端數(shù)據(jù)交互之從后端請(qǐng)求數(shù)據(jù)的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-08-08vue實(shí)現(xiàn)動(dòng)態(tài)添加數(shù)據(jù)滾動(dòng)條自動(dòng)滾動(dòng)到底部的示例代碼
本篇文章主要介紹了vue實(shí)現(xiàn)動(dòng)態(tài)添加數(shù)據(jù)滾動(dòng)條自動(dòng)滾動(dòng)到底部的示例代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-07-07Vue.js框架實(shí)現(xiàn)購(gòu)物車功能
這篇文章主要為大家詳細(xì)介紹了Vue.js框架實(shí)現(xiàn)購(gòu)物車功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-06-06VueUse功能精簡(jiǎn)你的dependencies
這篇文章主要為大家介紹了VueUse功能精簡(jiǎn)你的dependencies實(shí)現(xiàn)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07