怎么個百變法呢独郎,就是做一個組件过咬,可以實現(xiàn) input 的各種形態(tài)。
原生input的類型
先整理一下 input 的 type 都提供了哪些類型缰盏。
原:HTML5之前的類型。
新:HTML5提供的新的類型淹遵。
這里沒有寫 radio 和 checkbox口猜,因為這兩個被我劃分為選擇類型,同理還有submit透揣。
我們可以依據(jù)這個類型定義一個屬性:
const type = {
100: 'textarea', // 多行文本框
101: 'text', // 單行文本框
102: 'password', // 密碼
103: 'tel', // 電話
104: 'email', // 電子郵件
105: 'url', // url
106: 'search', // 搜索
107: 'color', // 顏色
108: 'text', // 彈窗選擇記錄
110: 'date', // 日期
111: 'datetime-local', // 日期時間
112: 'time', // 時間
113: 'week', // 年月
114: 'month', // 年周
120: 'number', // 數(shù)字
121: 'range', // 滑塊
130: 'file', // 上傳文件
131: 'file', // 上傳圖片
140: 'fulltext', // 富文本編輯器
150: 'checkbox', // 勾選
152: 'checkboxs', // 多選組
153: 'radios', // 單選組
170: 'select', // 下拉列表框 單選
171: 'selects', // 列表框 多選
172: 'selectMore' // 聯(lián)動下拉列表框
}
具體使用方式下面說暮的。
依據(jù) input 的屬性定義一個對象
然后我把可以把input的其他屬性整理出來做一個對象:
const meta = reactive({
controlId: 1000,
colName: 'companyName',
controlType: 101,
isClear: true,
disabled: false,
required: true,
readonly: false,
pattern: '',
class: '',
placeholder: '請輸入公司名稱',
title: '公司名稱',
autocomplete: 'on',
size: 30,
maxlength: 100,
optionList: [],
tdCount: 1
})
準(zhǔn)備工作做好了,我們開始做組件淌实。
做一個多功能的 文本類 控件
模板部分
<template>
<!---->
<input :id="'c' + meta.controlId"
:type="type[meta.controlType]"
:name="'c' + meta.controlId"
:value="modelValue"
:disabled="meta.disabled"
:readonly="meta.readonly"
:class="meta.class"
:placeholder="meta.placeholder"
:title="meta.title"
:size="meta.size"
:maxlength="meta.maxlength"
:autocomplete="meta.autocomplete"
:list="meta.optionKey"
@input="myInput"
:key="'ckey_'+meta.controlId">
<!--文本框的備選項-->
<datalist v-if="typeof(meta.optionKey)!=='undefined'" :id="meta.optionKey">
<option :key="item.value" v-for="item in meta.optionList" :label="item.title" :value="item.value" />
</datalist>
</template>
這個比較簡單冻辩,就是把 input 具有的屬性都給綁定上。
這里要感謝vue的數(shù)據(jù)綁定功能拆祈,沒有設(shè)置的屬性會自動省略恨闪,這就不用我們一個一個判斷是不是 undefined 了。
代碼部分
export default {
name: 'nf-h5-form-text',
props: {
modelValue: String,
meta: metaInput
},
emits: ['input'],
setup (props, context) {
console.log(props)
// 提交數(shù)據(jù)
const myInput = (e) => {
console.log(e)
console.log(context)
context.emit('update:modelValue', e.target.value)
}
return {
type,
myInput
}
}
}
這個比較簡單了放坏,設(shè)計兩個屬性咙咽,一個是 modelValue 綁定 input 的 value 的。
另一個是 meta淤年,后面跟了一個 metaInput 钧敞,這個就是上面整理的 input 的屬性對象蜡豹,在組件的屬性里面,改成了帶驗證的形式溉苛。
// 定義屬性
const metaInput = {
type: Object,
default: () => {
return {
// 通用
controlId: Number, // 編號镜廉,區(qū)別同一個表單里的其他控件
colName: String, // 字段名稱
controlType: Number, // 用類型編號表示type
isClear: {
// isClear 連續(xù)添加時是否恢復(fù)默認(rèn)值
type: Boolean,
default: false
},
defaultValue: String, // 默認(rèn)值
autofocus: { // 是否自動獲得焦點
type: Boolean,
default: false
},
disabled: {
// 是否禁用
type: Boolean,
default: false
},
required: { // 必填
type: Boolean,
default: true
},
readonly: { // 只讀
type: Boolean,
default: false
},
pattern: String, // 用正則做驗證。
class: {
type: String,
default: 'ant-input ant-input-sm'
},
placeholder: String,
title: String, // 提示信息
size: Number, // 字符寬度
maxlength: Number, // 最大字符數(shù)
autocomplete: { // off
type: String,
default: 'on'
},
optionKey: String, // 備選文字標(biāo)識
optionItem: Object // 備選的選項
}
}
}
這種方式愚战,不僅可以定義組件的屬性娇唯,而且還能對屬性做類型限制、設(shè)置默認(rèn)值等功能寂玲。
這樣可以讓屬性設(shè)置的更嚴(yán)謹(jǐn)一些塔插。
如果父組件里面設(shè)置屬性不符合要求,那么瀏覽器里面會給出來警告提示拓哟。
設(shè)計目的
為什么要這么設(shè)計呢想许?因為表單里面的元素是各種各樣的,比如文本断序、日期流纹、選擇等等,一般需要一個一個寫逢倍,即是是使用UI庫里的form,也還是需要進行具體屬性設(shè)置景图。
這個就有點郁悶了较雕,說好的數(shù)據(jù)綁定呢?
我比較懶挚币,對于這種需要一行一行寫的情況比較厭惡亮蒋,那么能不能簡單一點呢,比如使用v-for進行循環(huán)妆毕?
想要循環(huán)慎玖,那么就必須規(guī)范接口,也就是屬性和事件笛粘,這兩個統(tǒng)一之后我們就可以進行循環(huán)了趁怔。
如果可以循環(huán)的話,那么再大的表單也不用擔(dān)心了薪前,一個循環(huán)搞定润努。
這里只是處理了一下文本類的控件,后面還要處理選擇類的控件示括,還有其他控件铺浇。一路封裝下來,最后就可以實現(xiàn)v-for的目的了垛膝。