在使用taro开发小程序过程中,发现taro-ui 的 InputNumber 组件在小程序设置了最小值后,无法删除最小值,只能输入以最小值为起始的值,遂自己开发一个这样的组件来使用
上代码~
import { Input, View, Image } from "@tarojs/components";
import React from "react";
import Taro from "@tarojs/taro";
import classnames from "classnames";
// @ts-ignore
import plusSvg from "@/public/images/product/plus.svg";
// @ts-ignore
import MinuteSvg from "@/public/images/product/minute.svg";
// @ts-ignore
import MinuteDisableSvg from "@/public/images/product/minute-disabled.svg";
import "./index.scss";
export default function InputNumberCom(props) {
const { disabled, min, max, showToast = true } = props;
const addNum = (num1, num2) => {
let sq1, sq2, m;
try {
sq1 = num1.toString().split(".")[1].length;
} catch (e) {
sq1 = 0;
}
try {
sq2 = num2.toString().split(".")[1].length;
} catch (e) {
sq2 = 0;
}
m = Math.pow(10, Math.max(sq1, sq2));
return (Math.round(num1 * m) + Math.round(num2 * m)) / m;
};
const handleChangeStep = (type) => {
const { step = 1 } = props;
let { value } = props;
if (!value || Number.isNaN(+value)) {
value = min;
}
if (disabled) return null;
if (type === "minus") {
value = addNum(value, -step);
} else if (type === "plus") {
value = addNum(value, step);
}
console.log({ value, min, max }, "---handleChangeStep---");
showMaxToast(value);
if (value < min || value > max) return null;
handleEmit(value, type);
};
const handleMinus = () => {
props.value > min && handleChangeStep("minus");
};
const handlePlus = () => {
handleChangeStep("plus");
};
const showMaxToast = (value) => {
if (showToast && value > max) {
Taro.showToast({
icon: "none",
title: `最多只能买${max}件哦~`,
});
}
};
const handleValue = (e, type?: string) => {
let { value } = e.detail;
if (!value) {
if (type === "blur") {
setTimeout(() => {
handleEmit(min);
}, 10);
}
return;
}
value = +value;
showMaxToast(value);
if (value > max) {
value = max;
} else if (value < min) {
value = min;
}
return value;
};
const handleBlur = (e, type) => {
const value = handleValue(e, type);
handleEmit(value);
};
const handleEmit = (val, type?: string) => {
const data: any = {
value: val,
};
if (type) data.type = type;
props.onChange(data);
};
return (
<View className="input-number-com">
<View
className={classnames("input-number-com__minute", {
disabled: props.value <= min,
})}
onClick={handleMinus}
>
<Image src={props.value <= min ? MinuteDisableSvg : MinuteSvg} />
</View>
<Input
value={props.value}
disabled={disabled}
className="input-number-com__input"
type="number"
cursor={-1}
onBlur={(e) => handleBlur(e, "blur")}
onInput={(e) => handleBlur(e, "input")}
/>
<View
className={classnames("input-number-com__plus", {
disabled: props.value >= max,
})}
onClick={handlePlus}
>
<Image src={plusSvg} />
</View>
</View>
);
}
顺便贴上样式文件吧
.input-number-com {
display: flex;
align-items: center;
&__minute,
&__plus {
font-size: 24px;
padding: 16px;
image {
width: 16px;
height: 16px;
object-fit: contain;
}
}
.disabled {
color: #f2f2f2;
}
&__input {
background: #f2f2f2;
border-radius: 2px;
height: 36px;
width: 64px;
border-left: none;
border-right: none;
font-size: 24px;
text-align: center;
}
}
共勉之~