基於原生的 HTML 標籤進行擴充的 Input 元件。
Input 元件一般是一個元件庫的基礎,很多元件都需要依賴它,所以該元件的特點在於:
- 支援原生的功能,結合
this.$slots
擴充slot
,便於二次封裝; v-model
與v-on=$listeners
的相關處理;- 樣式的封裝以及抽離。
1. 例項
程式碼
<
!-- 基礎用法 -->
<
fat-input placeholder="請輸入內容" v-model="inputValue" />
<
!-- 複合型輸入框 -->
<
fat-input placeholder="請輸入內容">
<
template slot="prepend">
<
div class="prepend-part c-size-s">
Http://<
/div>
<
/template>
<
template slot="append">
<
div class="append-part c-size-s">
.com<
/div>
<
/template>
<
/fat-input>
複製程式碼
例項地址:Input 例項
程式碼地址:Github UI-Library
2. 原理
首先擴充 type
屬性,新增值為 textarea
的狀態,設計該元件的結構為 input
如下
<
div :class="['input-wrapper']">
<
textarea v-if="type === 'textarea'" class="textarea-inner" />
<
template v-else>
<
input :class="['input-inner']" :type="type" />
<
/template>
<
/div>
複製程式碼
基礎功能實現:
-
新增
v-bind="$attrs"
指令,來實現原生input
的相關屬性,例如placeholder
、readonly
、maxlength
等,在input
以及textarea
上,該指令能夠在元件上繫結父作用域中不作為 prop 被識別 (且獲取) 的特性 (class 和 style 除外); -
新增
v-on="$listeners"
指令,實現元件上的change
、focus
、blur
事件,由於 Input 元件需要支援v-model="inputValue"
,而在input
標籤 上v-model
依賴input
事件,其原理是event =>
this.$emit("input", event.target.value)複製程式碼但是直接使用時,
$emit("input", arg)
中arg
是一個[object InputEvent]
,與實際應用情況不服,兩者會報異常,這時利用 computed 屬性對$listeners
進行修改export default {
model: {
prop: "value", event: "input"
}, computed: {
inputListeners() {
return Object.assign({
}, this.$listeners, {
input: event =>
this.$emit("input", event.target.value)
});
}
}
};
複製程式碼然後再利用
v-on="inputListeners"
繫結到元件上,同時 watchvalue
,watch: {
value: {
handler(newVal) {
this.inputValue = newVal;
}, // 新增immediate,減少created生命週期中的賦值 immediate: true
}
}複製程式碼
樣式擴充實現:
- 新增icon(非
textarea
時生效),新增<
fat-icon v-if="prefixIcon" class="icon" :name="prefixIcon"/>
<
input :class="['input-inner']" :type="type" :value="inputValue" v-bind="$attrs" v-on="inputListeners"/>
<
fat-icon v-if="suffixIcon" class="icon" :name="suffixIcon"/>
複製程式碼 - 實現複合型輸入框時,主要依靠具名插槽
<
slot name="prepend">
<
/slot>
<
input :class="['input-inner', {
'have-prepand': havePrepand, 'have-append': haveAppend
}]" :type="type" :value="inputValue" v-bind="$attrs" v-on="inputListeners"/>
<
slot name="append">
<
/slot>
複製程式碼並且為了相容樣式,需要對
input-inner
新增兩個類,have-prepand
以及have-append
,它們的狀態主要是檢查this.$slots
物件computed: {
havePrepand() {
return this.$slots.prepend;
}, haveAppend() {
return this.$slots.append;
}
}複製程式碼
3. 使用
由於上述實現過程,都是在原生的 Input
元件進行的擴充,在實際應用時,可結合業務進行封裝以及抽象。使用時,主要注意點兩個具名插槽的使用。
<
div class="demo-row-content">
<
fat-input placeholder="請輸入內容">
<
template slot="prepend">
<
div class="prepend-part c-size-s">
Http://<
/div>
<
/template>
<
template slot="append">
<
div class="append-part c-size-s">
.com<
/div>
<
/template>
<
/fat-input>
<
/div>
複製程式碼
往期文章:
- 從零實現Vue的元件庫(零)- 基本結構以及構建工具
- 從零實現Vue的元件庫(一)- Toast 實現
- 從零實現Vue的元件庫(二)- Slider 實現
- 從零實現Vue的元件庫(三)- Tabs 實現
- 從零實現Vue的元件庫(四)- File-Reader 實現
- 從零實現Vue的元件庫(五)- Breadcrumb 實現
- 從零實現Vue的元件庫(六)- Hover-Tip 實現
- 從零實現Vue的元件庫(七)- Message-Box 實現
- 從零實現Vue的元件庫(八)- Input 實現
- 從零實現Vue的元件庫(九)- InputNumber 實現
- 從零實現Vue的元件庫(十)- Select 實現
- 從零實現Vue的元件庫(十一)- 結合 Functional Component 實現 Date-picker
- 從零實現Vue的元件庫(十二)- Table 實現
原創宣告: 該文章為原創文章,轉載請註明出處。