因項目中有多處輸入框要求只能輸入整數(shù)或者浮點數(shù), el-input 設(shè)置type=number 火狐瀏覽器這個屬性是無效的; 所以就想到了 使用el-input type=text 輸入的時候 正則匹配, 只能輸入整數(shù)或者浮點數(shù); 所以為了方便使用,需要對第三方庫el-input 進(jìn)行封裝。
1. 初始封裝的組件Number-input.vue 代碼如下:
<template>
<el-input
:value="value"
v-bind="$attrs"
type="text"
@input="handleInput"
/>
</template>
<script>
import Big from 'big.js';
export default {
inheritAttrs: false,
props: {
value: {
type: String | Number,
default: ''
},
precision: {
type: Number,
validator(val) {
return val >= 0 && val === parseInt(val, 10);
}
},
minPrecision: {
type: Number,
validator(val) {
return val >= 0 && val === parseInt(val, 10);
}
},
maxPrecision: {
type: Number,
default: Infinity,
validator(val) {
return val >= 0 &&(val === parseInt(val, 10) || val === Infinity);
}
},
isNumber: {
type: Boolean,
default: false
},
max: {
type: String | Number,
default: Infinity
},
min: {
type: String | Number,
default: -Infinity
}
},
methods: {
handleInput(val) {
console.log('ssssss===', val)
let reg = ''
if(this.maxPrecision === Infinity) {
// this.$emit('input', val)
reg = new RegExp(`^\\D*(\\d*(?:\\.\\d{0,20})?).*$`, 'g')
this.$emit('input', val.replace(reg ,'$1'))
} else if(this.maxPrecision >= 0) {
// 正則不能輸入最大位數(shù)
reg = new RegExp(`^\\D*(\\d*(?:\\.\\d{0,${this.maxPrecision}})?).*$`, 'g')
this.$emit('input', val.replace(reg ,'$1'))
}
val = val.replace(reg ,'$1')
this.$emit('input', val)
console.log('ssssss結(jié)束===', val)
},
handleInputChange(val) {
console.log('handleInputChange====', val, this.precision)
let newV = isNaN(val) ? '' : (val ? val.toString() : '')
if(newV) {
newV = this.getNewValue(val.toString())
}
this.$emit('input', newV)
},
getNewValue(val) {
// 根據(jù)精度獲取冪次數(shù), 獲取精度整數(shù)位 利用math.round 四舍五入 轉(zhuǎn)成float類型 再除以相同的10次冪 1.345直接利用tofixed(2) 取2位精度 會有問題
let newV = ''
let bigNewV = new Big(val)
let precisionArray = val.split('.')
let precision = precisionArray?.[1]?.length??0
if(this.minPrecision >= precision) {
newV = bigNewV.toFixed(this.minPrecision)
} else {
newV = bigNewV.toFixed(precision)
}
return newV
}
}
}
</script>
封裝第三方組件主要用到 $atrrs 和?$listeners?
v-bind="$attrs" v-on="$listeners"?
?$atrrs:接收父組件傳過來的非class 和 style , 并且未在props? 中注冊使用的屬性?
$listeners :接收父組件傳過來的非native 的事件
(注:.native 事件是父組件本身的事件, 在vue 中.native 只能用于組件上,.native 修飾符的作用是:在一個組件的根元素上直接監(jiān)聽一個原生事件; 原生的標(biāo)簽上不能使用 比如直接在<input @input.native='xxx' /> 會報錯)
2. 父組件 Add.vue? 中使用
<NumberInput
:maxPrecision="0"
v-model="quantity"
placeholder="請輸入"
clearable />
?上述使用目前為止都是正常的;
然后突然發(fā)現(xiàn)另外一個同事使用的時候 ,出現(xiàn)了問題!??!
在封裝的組件Number-input.vue中多寫一個屬性為了接收父組件傳過來的事件再傳給下一級:v-on="$listeners"
<template>
<el-input
:value="value"
v-bind="$attrs"
v-on="$listeners"
type="text"
@input="handleInput"
/>
</template>
和上述對比 導(dǎo)致除了數(shù)字其他還能輸入
原因就是 el-input 源碼中 通過?v-on="$listeners" 接收了 業(yè)務(wù)組件Add.vue 傳過來的事件, Add.vue 使用v-model 實現(xiàn)雙向綁定, 默認(rèn)有一個input 事件; 所以 當(dāng)輸入框輸入數(shù)據(jù)的時候 , el-input 源碼 中 觸發(fā)input 事件, 同時向外觸發(fā)?this.$emit('input', event.target.value) , 這個會先后觸發(fā)Number-input.vue 和 Add.vue 中的 input事件; Add.vue中默認(rèn)的input 事件接收的是 el-input 源碼中傳過來的原始值,會覆蓋掉 Number-input.vue 中傳過來的值,?最終v-model 中的值接收的也是el-input 源碼中傳過來的原始值.?
el-input 源碼
handleInput(event) {
// should not emit input during composition
// see: https://github.com/ElemeFE/element/issues/10516
if (this.isComposing) return;
// hack for https://github.com/ElemeFE/element/issues/8548
// should remove the following line when we don't support IE
if (event.target.value === this.nativeInputValue) return;
console.log('el-input input事件====', event)
this.$emit('input', event.target.value);
// ensure native input value is controlled
// see: https://github.com/ElemeFE/element/issues/12850
this.$nextTick(this.setNativeInputValue);
},
知道了原因所在,如何修復(fù)該問題:
1. Number-input 組件中的@input 和 @change事件 添加.native , 這樣的話 el-input 源碼中的 $emit('input' 就不會觸發(fā)這兩個事件 ; 這兩個事件 會添加到 組件的根元素上 ; 看 el-input 源碼可知 會添加到最外層的div 上; 然后 當(dāng)我們輸入數(shù)據(jù)的時候 ,首先$emit('input' 觸發(fā)的是Add.vue 中的input 事件改變value 值;接著?通過冒泡 會觸發(fā)父元素上的input 和 change事件, 在這 兩個事件中 手動又去觸發(fā)了 add.vue 中的input 事件(這個主要是自己怎么寫), 改變了 value 值, 最終改了輸入框的值文章來源:http://www.zghlxwxcb.cn/news/detail-436664.html
2. Number-input.vue中監(jiān)聽value 值的變化 類似下面: 但是這種 不能 區(qū)分是input 還是change事件文章來源地址http://www.zghlxwxcb.cn/news/detail-436664.html
watch: {
value: {
handler(val, oldV) {
let reg = ''
if(this.maxPrecision === Infinity) {
// this.$emit('input', val)
reg = new RegExp(`^\\D*(\\d*(?:\\.\\d{0,20})?).*$`, 'g')
this.$emit('input', val.replace(reg ,'$1'))
} else if(this.maxPrecision >= 0) {
// 正則不能輸入最大位數(shù)
reg = new RegExp(`^\\D*(\\d*(?:\\.\\d{0,${this.maxPrecision}})?).*$`, 'g')
this.$emit('input', val.replace(reg ,'$1'))
}
val = val.replace(reg ,'$1')
this.$emit('input', val)
}
}
},
到了這里,關(guān)于element-ui :封裝el-input 遇到的問題的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!