基于element?UI?input組件自行封裝“數(shù)字區(qū)間”輸入框組件的問題及解決

問題描述
在開發(fā)時(shí)遇到一個(gè)數(shù)字區(qū)間輸入框的需求,如下圖:

項(xiàng)目使用的是vue,組件庫用的是element UI,但是element UI并沒有提供數(shù)字區(qū)間組件,只提供了InputNumber 計(jì)數(shù)器輸入框,如果用兩個(gè)計(jì)數(shù)器輸入框進(jìn)行拼接也能滿足需求,但是樣式調(diào)試起來太過于復(fù)雜且不夠靈活,不能令人滿意,并且該數(shù)字區(qū)間輸入框在其它界面也有這種需求,于是就在element input輸入框的基礎(chǔ)上自行封裝了一個(gè)數(shù)字區(qū)間組件使用。
實(shí)現(xiàn)效果
實(shí)現(xiàn)效果如下:

使用方式如下:
<input-number-range :disabled="isDisabled" :precision="num" v-model="value"></input-number-range>
其中disabled屬性控制是否禁用,precision屬性控制精度默認(rèn)為0即只能輸入整數(shù),v-model雙向綁定要傳遞的值,該值是一個(gè)數(shù)組類型 [最小值,最大值]
另外該組件只能輸入數(shù)字,輸入其他非數(shù)字,或錯(cuò)誤數(shù)字(多個(gè)小數(shù))都會(huì)默認(rèn)為空;在先輸入最小值時(shí),如果后輸入的最大值小于最小值,則最大值默認(rèn)為最小值,同理先輸入最大值時(shí),如果后輸入的最小值大于最大值,則最小值默認(rèn)為最大值
實(shí)現(xiàn)代碼
實(shí)現(xiàn)代碼可以分為兩塊一塊為組件的封裝代碼,一塊為上述實(shí)現(xiàn)效果的演示代碼
數(shù)字區(qū)間組件代碼
<template>
<div>
<div class="input-number-range" :class="{ 'is-disabled': disabled }">
<div class="flex">
<div class="from">
<!--
blur:最小值失焦事件
focus:最小值聚焦事件
input:最小值輸入事件
change:最小值change事件
-->
<el-input
ref="input_from"
v-model="userInputForm"
:disabled="disabled"
placeholder="最小值"
@blur="handleBlurFrom"
@focus="handleFocusFrom"
@input="handleInputFrom"
@change="handleInputChangeFrom"
></el-input>
</div>
<div class="center">
<span>至</span>
</div>
<div class="to">
<!--
blur:最大值失焦事件
focus:最大值聚焦事件
input:最大值輸入事件
change:最大值change事件
-->
<el-input
ref="input_to"
v-model="userInputTo"
:disabled="disabled"
placeholder="最大值"
@blur="handleBlurTo"
@focus="handleFocusTo"
@input="handleInputTo"
@change="handleInputChangeTo"
></el-input>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: "InputNumberRange",
/** 組件接收參數(shù) */
props: {
value: { required: true },
// 是否禁用
disabled: {
type: Boolean,
default: false,
},
// 精度參數(shù)
precision: {
type: Number,
default: 0,
validator(val) {
return val >= 0 && val === parseInt(val, 10);
},
},
},
data() {
return {
userInputForm: null, // 最小值
userInputTo: null, // 最大值
};
},
watch: {
/** 監(jiān)聽value實(shí)現(xiàn)雙向綁定 */
value: {
immediate: true,
handler(value) {
// 判斷是否為數(shù)字number類型
if (value instanceof Array && this.precision !== undefined) {
let fromVal =
value[0] && typeof value[0] === "number" ? value[0] : null;
let toVal =
value[1] && typeof value[1] === "number" ? value[1] : null;
this.userInputForm = fromVal ? fromVal : null;
this.userInputTo = toVal ? toVal : null;
}
},
},
},
methods: {
// 根據(jù)精度保留數(shù)字
toPrecision(num, precision) {
if (precision === undefined) precision = 0;
return parseFloat(
Math.round(num * Math.pow(10, precision)) / Math.pow(10, precision)
);
},
/** 觸發(fā)以下事件時(shí)自動(dòng)向上冒泡執(zhí)行(通過emit將事件拋給element input組件) */
handleBlurFrom(event) {
this.$emit("blurfrom", event);
},
handleFocusFrom(event) {
this.$emit("focusfrom", event);
},
handleBlurTo(event) {
this.$emit("blurto", event);
},
handleFocusTo(event) {
this.$emit("focusto", event);
},
handleInputFrom(value) {
this.$emit("inputfrom", value);
this.userInputFrom = value;
},
handleInputTo(value) {
this.$emit("inputto", value);
this.userInputTo = value;
},
// from輸入框change事件
handleInputChangeFrom(value) {
const newVal = this.setPrecisionValue(value);
this.userInputForm = newVal;
// 如果初始化數(shù)字的精度不符合代碼設(shè)置時(shí)重置數(shù)字
this.userInputTo = this.setPrecisionValue(this.userInputTo);
if (!this.userInputForm && !this.userInputTo) {
this.$emit("input", []);
this.$emit("changefrom", newVal);
return;
}
if (!this.userInputTo) {
this.userInputForm = newVal;
} else {
// 最小值大于最大值時(shí)邏輯判斷
this.userInputForm =
!newVal || parseFloat(newVal) <= parseFloat(this.userInputTo)
? newVal
: this.userInputTo;
}
this.$emit("input", [this.userInputForm, this.userInputTo]);
this.$emit("changefrom", newVal);
},
// to輸入框change事件
handleInputChangeTo(value) {
const newVal = this.setPrecisionValue(value);
this.userInputTo = newVal;
this.userInputForm = this.setPrecisionValue(this.userInputForm);
if (!this.userInputTo && !this.userInputForm) {
this.$emit("input", []);
this.$emit("changefrom", newVal);
return;
}
if (!this.userInputForm) {
this.userInputTo = newVal;
} else {
// 最大值小于最小值時(shí)邏輯判斷
this.userInputTo =
!newVal || parseFloat(newVal) >= parseFloat(this.userInputForm)
? newVal
: this.userInputForm;
}
this.$emit("input", [this.userInputForm, this.userInputTo]);
this.$emit("changeto", newVal);
},
// 設(shè)置成精度數(shù)字
setPrecisionValue(value) {
if (!value) return null;
const newVal = Number(value);
// 如果是非數(shù)字空返回null
if (isNaN(value)) return null;
if (typeof newVal === "number" && this.precision !== undefined) {
const val = this.toPrecision(value, this.precision);
return val;
}
return null;
},
},
};
</script>
<style lang="scss" scoped>
// 取消element原有的input框樣式
::v-deep .el-input .el-input__inner {
border: 0px;
margin: 0;
padding: 0 15px;
background-color: transparent;
text-align: center;
}
.input-number-range {
background-color: #fff;
border: 1px solid #dcdfe6;
border-radius: 4px;
}
.flex {
display: flex;
flex-direction: row;
width: 100%;
justify-content: center;
align-items: center;
.center {
margin-top: 1px;
}
}
.is-disabled {
background-color: #f5f7fa;
border-color: #e4e7ed;
color: #c0c4cc;
cursor: not-allowed;
}
</style>上述就是完整的組件代碼,寫好組件代碼后,就是在項(xiàng)目中使用,有兩種方式,一種是使用時(shí)在通過引用進(jìn)行使用如下:
<template>
<div>
<InputNumberRange></InputNumberRange>
</div>
</template>
<script>
import InputNumberRange from './components/inputNumberRange.vue'
export default {
name: "XXXX"
components: {
InputNumberRange,
},
data() {}
}
</script>另一種方式是在main.js中進(jìn)行全局組測(cè),這樣就可以自由使用<input-number-range>標(biāo)簽,如下:
import InputNumberRange from './components/inputNumberRange.vue' Vue.component(InputNumberRange.name, InputNumberRange)
示例演示代碼
<template>
<div class="main">
<!-- 演示操作按鈕模塊 -->
<div class="caseHeader">
<div>
<el-switch
v-model="isDisabled"
size="small"
active-text="禁用"
@change="switchChange"
>
</el-switch>
</div>
<div style="display: flex">
<span>精度:</span>
<el-input-number
size="small"
v-model="num"
@change="precisionChange"
:min="0"
:max="10"
label="描述文字"
></el-input-number>
</div>
<div>
<el-button type="link" size="small" @click="reset">重置</el-button>
</div>
</div>
<!-- 數(shù)字區(qū)間使用模塊 -->
<div class="numberRange">
<el-form ref="form" :model="formData" label-width="80px">
<el-form-item label="數(shù)字區(qū)間">
<input-number-range
:disabled="isDisabled"
:precision="num"
v-model="formData.numberRange"
></input-number-range>
</el-form-item>
</el-form>
</div>
</div>
</template>
<script>
export default {
name: "TestCase",
data() {
return {
isDisabled: false, // 是否禁用
num: 0, // 精度
formData: {
numberRange: [],
},
};
},
methods: {
/** 重置方法 */
reset() {
this.formData.numberRange = [];
}
},
};
</script>
<style lang="scss" scoped>
.main {
width: 100%;
margin: 16px;
position: relative;
}
.numberRange {
width: 400px;
}
.caseHeader {
width: 400px;
display: flex;
justify-content: space-between;
margin: 24px;
}
</style>上述就是數(shù)字區(qū)間輸入組件的實(shí)現(xiàn)即演示內(nèi)容
到此這篇關(guān)于基于element UI input組件自行封裝“數(shù)字區(qū)間”輸入框組件的文章就介紹到這了,更多相關(guān)element UI數(shù)字區(qū)間輸入組件內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用JavaScript?將數(shù)據(jù)網(wǎng)格綁定到?GraphQL?服務(wù)的操作方法
GraphQL是管理JavaScript應(yīng)用程序中數(shù)據(jù)的優(yōu)秀工具,本教程展示了GraphQL和SpreadJS如何簡(jiǎn)單地構(gòu)建應(yīng)用程序,?GraphQL?和?SpreadJS都有更多功能可供探索,因此您可以做的事情遠(yuǎn)遠(yuǎn)超出了這個(gè)示例,感興趣的朋友一起看看吧2023-11-11
微信小程序清空輸入框信息與實(shí)現(xiàn)屏幕往上滾動(dòng)的示例代碼
這篇文章主要介紹了微信小程序清空輸入框信息與實(shí)現(xiàn)屏幕往上滾動(dòng)的示例代碼,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-06-06
如何在JavaScript中使用map()迭代數(shù)組詳細(xì)步驟
在JavaScript中循環(huán)迭代數(shù)組的方法有很多種,下面這篇文章主要給大家介紹了關(guān)于如何在JavaScript中使用map()迭代數(shù)組的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-02-02
JavaScript數(shù)字和字符串轉(zhuǎn)換示例
這篇文章主要介紹了JavaScript數(shù)字和字符串轉(zhuǎn)換的應(yīng)用,需要的朋友可以參考下2014-03-03
點(diǎn)擊button獲取text內(nèi)容并改變樣式的js實(shí)現(xiàn)
這篇文章主要介紹了點(diǎn)擊button獲取text內(nèi)容并改變樣式的js實(shí)現(xiàn),經(jīng)測(cè)試非常實(shí)用,需要的朋友可以參考下2014-09-09
jQuery實(shí)現(xiàn)手風(fēng)琴特效
這篇文章主要為大家詳細(xì)介紹了前端js實(shí)現(xiàn)手風(fēng)琴效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-01-01
微信小程序如何刷新當(dāng)前界面的實(shí)現(xiàn)方法
這篇文章主要介紹了微信小程序如何刷新當(dāng)前界面的實(shí)現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用小程序具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-06-06
js移動(dòng)焦點(diǎn)到最后位置的簡(jiǎn)單方法
下面小編就為大家?guī)硪黄猨s移動(dòng)焦點(diǎn)到最后位置的簡(jiǎn)單方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-11-11

