Vue3組件(二)做一個百變input組件

怎么個百變法呢,就是做一個組件,可以實現 input 的各種形態。

原生input的類型

先整理一下 input 的 type 都提供了哪些類型。
原:HTML5之前的類型。
新:HTML5提供的新的類型。

input 類型.png

這里沒有寫 radio 和 checkbox,因為這兩個被我劃分為選擇類型,同理還有submit。

我們可以依據這個類型定義一個屬性:

    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', // 數字
      121: 'range', // 滑塊
      130: 'file', // 上傳文件
      131: 'file', // 上傳圖片
      140: 'fulltext', // 富文本編輯器
      150: 'checkbox', // 勾選
      152: 'checkboxs', // 多選組
      153: 'radios', // 單選組
      170: 'select', // 下拉列表框 單選
      171: 'selects', // 列表框 多選
      172: 'selectMore' // 聯動下拉列表框
    }

具體使用方式下面說。

依據 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
    })

準備工作做好了,我們開始做組件。

做一個多功能的 文本類 控件

模板部分

<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的數據綁定功能,沒有設置的屬性會自動省略,這就不用我們一個一個判斷是不是 undefined 了。

代碼部分

export default {
  name: 'nf-h5-form-text',
  props: {
    modelValue: String,
    meta: metaInput
  },
  emits: ['input'],
  setup (props, context) {
    console.log(props)
    // 提交數據
    const myInput = (e) => {
      console.log(e)
      console.log(context)
      context.emit('update:modelValue', e.target.value)
    }

    return {
      type,
      myInput
    }
  }
}

這個比較簡單了,設計兩個屬性,一個是 modelValue 綁定 input 的 value 的。
另一個是 meta,后面跟了一個 metaInput ,這個就是上面整理的 input 的屬性對象,在組件的屬性里面,改成了帶驗證的形式。

// 定義屬性
const metaInput = {
  type: Object,
  default: () => {
    return {
      // 通用
      controlId: Number, // 編號,區別同一個表單里的其他控件
      colName: String, // 字段名稱
      controlType: Number, // 用類型編號表示type
      isClear: {
        // isClear  連續添加時是否恢復默認值
        type: Boolean,
        default: false
      },
      defaultValue: String, // 默認值
      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, // 最大字符數
      autocomplete: { // off
        type: String,
        default: 'on'
      },
      optionKey: String, // 備選文字標識
      optionItem: Object // 備選的選項
    }
  }
}

這種方式,不僅可以定義組件的屬性,而且還能對屬性做類型限制、設置默認值等功能。
這樣可以讓屬性設置的更嚴謹一些。

如果父組件里面設置屬性不符合要求,那么瀏覽器里面會給出來警告提示。

設計目的

為什么要這么設計呢?因為表單里面的元素是各種各樣的,比如文本、日期、選擇等等,一般需要一個一個寫,即是是使用UI庫里的form,也還是需要進行具體屬性設置。

這個就有點郁悶了,說好的數據綁定呢?
我比較懶,對于這種需要一行一行寫的情況比較厭惡,那么能不能簡單一點呢,比如使用v-for進行循環?

想要循環,那么就必須規范接口,也就是屬性和事件,這兩個統一之后我們就可以進行循環了。

如果可以循環的話,那么再大的表單也不用擔心了,一個循環搞定。

這里只是處理了一下文本類的控件,后面還要處理選擇類的控件,還有其他控件。一路封裝下來,最后就可以實現v-for的目的了。

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容