從零實現Vue的元件庫(九)- InputNumber 實現
阿新 • • 發佈:2019-01-04
InputNumer 元件的難點在於:基於 Input 元件進行拓展的 InputNumber 元件
- 實現滑鼠長按,計數器數值變動;
- 導致 InputNumber 元件的值變化,有以下操作v-model繫結值的變化,加、減按鈕,input元件的輸入,需要對上述結果進行處理,所以如何設計合理模式,減少冗餘程式碼。
1. 例項
程式碼
<!-- 基礎用法 -->
<fat-input-number v-model="value" />
<!-- 禁用狀態 -->
<fat-input-number disabled />
<!-- 步數 -->
<fat-input-number :step="5" v-model="stepValue" />
<!-- 最大,最小值限制 -->
<fat-input-number :max="20" :min="0" :step="5" v-model="value" />
複製程式碼
例項地址:InputNumber 例項
程式碼地址:Github UI-Library
2. 原理
首先利用 Input 元件,在其 slot prepend
和 slot append
兩個插槽內,插入相應的加、減按鈕,具體如下。
<fat-input
class="input-number-inner"
type="text"
:disabled="disabled"
v-model="inputValue"
v-bind="$attrs"
>
<template slot="prepend">
<div
:class="['prepend-part', { 'is-disabled': addDisabled }]"
@mousedown.stop="!addDisabled && handleClick('add')"
>
<fat-icon name="add" size="16"/>
</div>
</template>
<template slot="append">
<div
:class="['append-part', { 'is-disabled': decDisabled }]"
@mousedown.stop="!decDisabled && handleClick('dec')"
>
<fat-icon name="remove" size="16"/>
</div>
</template>
</fat-input>
複製程式碼
接下來實現加、減按鈕的長按功能,其本質就是將 click
事件分為了,mousedown
以及 mouseup
兩個事件來處理,具體體現在 handleClick
函式。
handleClick(type) {
const { step } = this;
const period = 100;
const timerHandler = () => {
const { addDisabled, decDisabled } = this;
if (!addDisabled && type === "add") this.inputNumberValue += step;
if (!decDisabled && type === "dec") this.inputNumberValue -= step;
};
const timer = setInterval(timerHandler, period);
const startTime = new Date();
const handler = () => {
const endTime = new Date();
if (endTime - startTime < period) timerHandler();
clearInterval(timer);
document.removeEventListener("mouseup", handler, false);
};
document.addEventListener("mouseup", handler, false);
}
複製程式碼
首先,監聽按鈕的 mousedown
,當它觸發時完成以下操作:
- 記錄觸發時間
startTime
; - 定義一個
setInterval
,每隔一個period
就呼叫相應的timerHandler
函式,來模擬長按操作; - 在
document
上監聽mouseup
事件,當滑鼠還原時觸發。
然後,當滑鼠還原時,就會觸發 document
的 mouseup
事件,此時相應的處理為:
- 記錄觸發時間為
endTime
,如果滿足endTime - startTime < period
條件,則執行一次timerHandler
; - 利用
clearInterval
停止setInterval
,之後移除對mouseup
的監聽。
由於每次修改 InputNumber 元件的值時,都需判斷是否超出最大、最小值、或是輸入的值是否為數字等規則,即使將這些規則抽象為一個函式,也會顯得程式碼有些臃腫,所以選用 computed
屬性對 inputValue
狀態進行一層代理,具體如下
computed: {
inputNumberValue: {
get() {
return this.inputValue;
},
set(value) {
const { min, max, inputValue } = this;
const limits = [{
need: value => !isNum(value),
value: inputValue
}, {
need: value => value >= max,
value: max
}, {
need: value => value <= min,
value: min
}, {
need: () => true,
value: value
}];
this.inputValue = limits.find(limit => limit.need(value)).value;
}
}
}
複製程式碼
將對 inputValue
的修改,轉變為對 inputNumberValue
的修改,同時劫持 get
,set
函式,在 set
中,定義規則。
3. 使用
實現了基礎的InputNumber,後續可以在自行在樣式上進行擴充套件。
<!-- 基礎用法 -->
<fat-input-number v-model="value" />
<!-- 禁用狀態 -->
<fat-input-number disabled />
<!-- 步數 -->
<fat-input-number :step="5" v-model="stepValue" />
<!-- 最大,最小值限制 -->
<fat-input-number :max="20" :min="0" :step="5" v-model="value" />
複製程式碼
往期文章:
- 從零實現Vue的元件庫(零)- 基本結構以及構建工具
- 從零實現Vue的元件庫(一)- Toast 實現
- 從零實現Vue的元件庫(二)- Slider 實現
- 從零實現Vue的元件庫(三)- Tabs 實現
- 從零實現Vue的元件庫(四)- File-Reader 實現
- 從零實現Vue的元件庫(五)- Breadcrumb 實現
- 從零實現Vue的元件庫(六)- Hover-Tip 實現
- 從零實現Vue的元件庫(七)- Message-Box 實現
- 從零實現Vue的元件庫(八)- Input 實現
- 從零實現Vue的元件庫(九)- InputNumber 實現
原創宣告: 該文章為原創文章,轉載請註明出處。