uni-app数字输入框组件
【代码】uni-app数字输入框组件。
·
<template>
<view class="flex" :style="{ width, height }">
<view class="count-box flex align-center flex-1" :class="[wrong ? 'box-red' : '']" :style="[{borderColor: customBorderColor, borderRadius: addUnitRpx(radius)}]">
<view v-if="showStepButton" class="count-less count-pub" :style="[stepLessStyle]" @tap.stop="less" @longpress="longpressLess" @touchend="handletouchend">
<slot name="left">
-
</slot>
</view>
<!-- #ifdef H5 -->
<input
type="text"
@input="inputChange"
:placeholder="placeholder"
:disabled="inputDisable"
v-model="myValue"
@focus="onFocus"
@blur="onBlur"
class="count-input flex-1"
:style="[inputStyle]"
:inputmode="isDecimal?'text':'numeric'"
/>
<!-- #endif -->
<!-- #ifndef H5 -->
<input
type="digit"
@input="inputChange"
:placeholder="placeholder"
:disabled="inputDisable"
v-model="myValue"
@focus="onFocus"
@blur="onBlur"
class="count-input flex-1"
:style="[inputStyle]"
/>
<!-- #endif -->
<view v-if="showStepButton" class="count-add count-pub" :style="[stepAddStyle]" @tap.stop="add" @longpress="longpressAdd" @touchend="handletouchend">
<slot name="right">
+
</slot>
</view>
<view :ref="elId" :id="elId" v-if="isShowUnit" class="px-2 unit count-pub text-center" :style="unitStyle">{{ unit }}</view>
</view>
</view>
</template>
<script>
export default {
name: 'yl-input-number',
props: {
// 计数器中的值
value: {
type: [Number, String],
default: () => ''
},
// 输入框提示文字
placeholder: {
type: String,
default: ''
},
// 输入框字体颜色
inputColor: {
type: String,
default: 'inherit'
},
// 输入框背景颜色
inputBg: {
type: String,
default: ''
},
// 字体大小
fontSize: {
type: String,
default: 'inherit'
},
// 边框颜色
borderColor: {
type: String,
default: '#e4e4e4'
},
// 边框圆角
radius: {
type: String | Number,
default: '10rpx'
},
// 是否禁用
disabled: {
type: Boolean,
default: false
},
// 是否是小数
isDecimal: {
type: Boolean,
default: false
},
// 小数位数
decimalNumber: {
type: Number,
default: 2
},
// 最大值
max: {
type: Number,
default: 10000
},
// 最小值
min: {
type: Number,
default: -10000
},
// 是否展示+-按钮
showStepButton: {
type: Boolean,
default: false
},
// 步进器背景色
stepBg: {
type: String,
default: '#f5f7fa'
},
// 步进器字体颜色
stepColor: {
type: String,
default: '#555555'
},
// 加减按钮点击计时器
delayed: {
type: Number,
default: 200
},
step: {
type: Number,
default: 1
},
/* 盒子宽度 */
width: {
type: String,
default: '220rpx'
},
/* 盒子高度 */
height: {
type: String,
default: '64rpx'
},
/* 对齐方式 */
textAlign: {
type: String,
default: ''
},
/* 单位 */
unit: {
type: String,
default: ''
},
/* 单位背景色 */
unitBg: {
type: String,
default: '#f5f7fa'
},
/* 单位字体色 */
unitColor: {
type: String,
default: '#555555'
},
/* 是否显示单位 */
isShowUnit: {
type: Boolean,
default: false
},
},
data() {
const elId = `Uni_${Math.ceil(Math.random() * 10e5).toString(36)}`;
return {
myValue: '', // input绑定值
status: false, // 是否聚焦
timer: null, // 计时器
wrong: false, // 错误
elId: elId, // 唯一标识
addPositon:0,// 加号距离右侧的位置
};
},
created() {
this.myValue = this.value;
},
mounted() {
if (this.isShowUnit) {
// #ifdef H5
this.addPositon = this.$refs[this.elId].$el.scrollWidth
// #endif
}
},
watch: {
value(val) {
this.myValue = val;
}
},
computed:{
// 边框颜色
customBorderColor () {
if(this.borderColor == 'transparent') {
return 'transparent'
} else {
return this.status ? this.$getDarkColor(this.borderColor, 0.3) : this.borderColor
}
},
// 是否禁用
inputDisable(){
return this.disable
},
// 单位区域style
unitStyle(){
return {
background: this.unitBg,
color: this.unitColor
}
},
// 输入框样式
inputStyle() {
let style = { 'text-align': this.textAlign, color: this.inputColor, background: this.inputBg, fontSize: this.fontSize}
return {...style}
},
// 步进器【减】背景样式和字体
stepLessStyle(){
return {
backgroundColor: this.stepBg,
color: this.stepColor,
opacity: this.myValue <= this.min ? 0.4 : 1
}
},
// 步进器【加】背景样式和字体
stepAddStyle(){
return {
backgroundColor: this.stepBg,
color: this.stepColor,
opacity: this.myValue >= this.max ? 0.4 : 1
}
}
},
methods: {
// 添加rpx单位
addUnitRpx(value) {
if(/\d$/.test(value)){
return value + 'rpx'
} else {
return value
}
},
onFocus() {
this.$emit('focus')
this.status = true;
},
/**
* 失去焦点
*/
onBlur() {
this.$emit('blur')
this.status = false
this.wrong = false
if (this.myValue !== '' && this.myValue < this.min) {
this.myValue = '';
uni.showToast({
icon: 'none',
title: `输入范围在${this.min}到${this.max}之间`
});
this.$emit('changeVal', this.myValue);
this.$emit('update:value', this.myValue);
this.$emit('input', this.myValue)
}
},
/**
* 加
*/
add() {
if (this.disabled) {
return;
}
this.addPublick();
},
/**
* 执行值加
*/
addPublick() {
if (this.myValue >= this.max) {
this.status = false;
this.myValue = this.max;
clearInterval(this.timer);
} else {
this.myValue = +this.myValue + this.step;
}
this.$emit('update:value', this.myValue);
this.$emit('input', this.myValue)
this.handleChange();
},
/**
* 长按加
*/
longpressAdd() {
if (this.disabled) {
return;
}
this.timer = setInterval(() => {
this.addPublick();
}, this.delayed);
},
/**
* 减
*/
less() {
if (this.disabled) {
return;
}
this.lessPublick();
},
/**
* 执行减
*/
lessPublick() {
if (this.myValue <= this.min) {
clearInterval(this.timer);
this.status = false;
this.myValue = this.min;
} else {
// this.status = true;
this.myValue = this.myValue - this.step;
}
this.$emit('update:value', this.myValue);
this.$emit('input', this.myValue);
this.handleChange();
},
/**
* 长按减
*/
longpressLess() {
if (this.disabled) {
return;
}
this.timer = setInterval(() => {
this.lessPublick();
}, this.delayed);
},
handletouchend() {
clearInterval(this.timer);
},
/**
* 输入
* @param {Object} e
*/
inputChange(e) {
let value = e.detail.value;
let reg = /^(-?\d*(\.\d*)?).*$/;
value = value.match(reg)[1];
this.$nextTick(() => {
this.myValue = value;
});
if (value !== '') {
// 是否位小数
if (this.isDecimal) {
//正则表达试,默认两位小数
let reg = new RegExp(`^-?\\d*(\\.?\\d{0,${this.decimalNumber}})`, 'g');
value = value.match(reg)[0] || null;
let flag = false;
flag = value === '.' || value === '-' || /\.$/.test(value) || /0$/.test(value);
//重新赋值给input
this.$nextTick(() => {
this.myValue = flag ? value : Number(value);
});
} else {
if (/(\d*)\.*$/.test(value)) {
// 整数
value = value.match(/^(-?\d*)\.*$/)[1] || null;
}
// 新赋值给input
this.$nextTick(() => {
this.myValue = value === '-' ? value : +value;
});
}
// 输入超过最大取最大,小于最小取最小
if (+value > this.max) {
this.$nextTick(() => {
this.myValue = +this.max;
});
} else if (+value < this.min) {
this.wrong = true;
this.$nextTick(() => {
this.myValue = +this.min
});
} else {
this.wrong = false;
}
}
this.$nextTick(() => {
this.$emit('update:value', this.myValue);
this.$emit('input', this.myValue);
this.$emit('changeVal', this.myValue);
this.handleChange();
});
},
/**
* change事件
*/
handleChange() {
this.$emit('change', this.myValue);
},
//将hex颜色值str转化成rgb数组
$HexToRgb (str) {
let r = /^\#?[0-9a-fA-F]{6}$/;
//test方法检查在字符串中是否存在一个模式,如果存在则返回true,否则返回false
if (!r.test(str)) return console.error("输入错误的hex颜色值");
//replace替换查找的到的字符串
str = str.replace("#", "");
//match得到查询数组
let hxs = str.match(/../g);
for (let i = 0; i < 3; i++) hxs[i] = parseInt(hxs[i], 16);
return hxs;
},
//将rgb颜色值为a,b,c转化成hex颜色值
$RgbToHex (a, b, c) {
let r = /^\d{1,3}$/;
if (!r.test(a) || !r.test(b) || !r.test(c)) return console.error("输入错误的rgb颜色值");
let hexs = [a.toString(16), b.toString(16), c.toString(16)];
for (let i = 0; i < 3; i++) if (hexs[i].length == 1) hexs[i] = "0" + hexs[i];
return "#" + hexs.join("");
},
//得到hex颜色值为color的加深颜色值,level为加深的程度,限0-1之间
$getDarkColor (color, level) {
color = color.toLowerCase()
let r = /^\#?[0-9a-f]{6}$/;
if (!r.test(color)) return console.error("输入错误的hex颜色值");
let rgbc = this.$HexToRgb(color);
//floor 向下取整
for (let i = 0; i < 3; i++) rgbc[i] = Math.floor(rgbc[i] * (1 - level));
return this.$RgbToHex(rgbc[0], rgbc[1], rgbc[2]);
}
}
};
</script>
<style lang="less" scoped>
.flex{
display: flex;
flex-direction: row;
}
.align-center{
align-items: center;
}
.flex-1{
flex: 1;
}
.gray {
background: #eef3f9;
color: #555555;
}
.light {
background: #f5f7fa;
color: #c8c7cc;
}
.count-box {
position: relative;
height: 100%;
box-sizing: border-box;
z-index: 1;
transition: all 0.3s;
border-width: 1px;
border-style: solid;
}
.box-red {
border: 1px solid #f56c6c;
}
.count-pub {
min-width: 60rpx;
line-height: 60rpx;
height: 100%;
text-align: center;
font-size: 20px;
}
.count-less {
left: 0;
border-top-left-radius: 4px;
border-bottom-left-radius: 4px;
}
.count-add {
right: 0;
border-top-right-radius: 4px;
border-bottom-right-radius: 4px;
}
.count-input {
flex: 1;
height: 100% !important;
padding: 6rpx 10rpx;
border-radius: 5px;
box-sizing: border-box;
color: #808080;
font-size: 26rpx;
text-align: center;
}
.unit {
right: 0;
font-size: 28rpx;
border-top-right-radius: 4px;
border-bottom-right-radius: 4px;
}
</style>
使用:
<!-- 基本用法 -->
<yl-input-number :value="value1"></yl-input-number>
<!-- 输入字体颜色 -->
<yl-input-number inputColor="#77fBf9" :value="value1"></yl-input-number>
<!-- 边框颜色 -->
<yl-input-number borderColor="#77fBf9" :value="value1"></yl-input-number>
<!-- 最大、最小值(max:1000、min:-1000) -->
<yl-input-number :max="1000" :min="-1000" :value="value1"></yl-input-number>
<!-- 显示步进器按钮(showStepButton) -->
<yl-input-number :value="value2" showStepButton></yl-input-number>
<!-- 步进器按钮背景色和字体色 -->
<yl-input-number :value="value2" showStepButton stepBg="#7799FF" stepColor="#77FFFF"></yl-input-number>
<!-- 自定义步进器按钮 -->
<yl-input-number :value="value2" showStepButton>
<template slot="left">
<!-- 自定义icon(需替换) -->
<yl-icon color="#7799FF" name="direction-left"></yl-icon>
</template>
<template slot="right">
<yl-icon color="red" name="direction-right"></yl-icon>
</template>
</yl-input-number>
<!-- 步进器步长(step:10) -->
<yl-input-number :value="value2" showStepButton :step="10"></yl-input-number>
<!-- 显示单位 -->
<yl-input-number isDecimal :value="value3" isShowDw unit="kg"></yl-input-number>
<!-- 对齐方式(left, center, right) -->
<yl-input-number textAlign="left" :value="value2"></yl-input-number>
<yl-input-number textAlign="center" :value="value4"></yl-input-number>
<yl-input-number textAlign="right" :value="value4"></yl-input-number>
<!-- 宽度(width:100%) -->
<yl-input-number width="100%" :value="value2"></yl-input-number>
更多推荐
已为社区贡献4条内容
所有评论(0)