افزایش تجربه کاربر با یک مؤلفه ورودی شماره سفارشی در React

در توسعه وب ، به ویژه برای برنامه هایی که نیاز به تعامل مکرر با داده های عددی دارند ، ارائه یک تجربه کاربر صاف و بدون خطا بسیار مهم است. یک مؤلفه ورودی شماره به خوبی طراحی شده نه تنها تعامل کاربر را تسهیل می کند بلکه تضمین می کند که داده های وارد شده معتبر و به درستی قالب بندی شده اند. در این مقاله ، ما یک مؤلفه React به نام را کشف خواهیم کرد سفارشی، طراحی شده برای رسیدگی به ورودی های عددی به طور کارآمد و بهبود تجربه کاربر.
مؤلفه CustomNumberInput چه کاری انجام می دهد؟
مؤلفه CustomNumberInput یک قسمت ورودی سفارشی است که به کاربران امکان می دهد اعداد را از جمله مقادیر اعشاری و منفی وارد کنند. این تضمین می کند که داده های وارد شده به قوانین خاص قالب بندی ، مانند تعداد smaximum از رقم عدد صحیح و اعشاری پایبند باشند. علاوه بر این ، به طور خودکار اعتبار و قالب بندی مقادیر وارد شده را کنترل می کند ، احتمال خطاها و بهبود قابلیت استفاده را کاهش می دهد.
در اینجا یک مثال سریع از نحوه استفاده از مؤلفه CustomNumberInput در برنامه خود آورده شده است:
import { CustomNumberInput } from './CustomNumberInput';
function App() {
const handleNumberChange = (value: string | null) => {
console.log("Entered value:", value);
};
return (
);
}
export default App;
در این مثال ، از مؤلفه CustomNumberInput استفاده می شود تا کاربران بتوانند عددی را با حداکثر 5 رقم عدد صحیح و 2 رقم اعشاری وارد کنند. از OnChange Prop برای رسیدگی به مقدار وارد شده استفاده می شود که به کنسول وارد شده است.
ویژگی های کلیدی
- قالب بندی شماره: این مؤلفه تضمین می کند که شماره های وارد شده به درستی قالب بندی شوند ، از جمله رسیدگی به علائم منفی و مثبت و همچنین جداکننده های اعشاری.
- اعتبار سنجی ورودی: فقط کاراکترهای عددی ، به علاوه و منهای علائم و جداکننده های اعشاری مجاز است. این امر مانع از ورود کاربران به شخصیت های نامعتبر می شود.
- کنترل رقم: این مؤلفه به شما امکان می دهد حداکثر تعداد رقم عدد عدد صحیح و اعشاری را که می توانند وارد شوند تعریف کنید ، که برای برنامه های کاربردی که نیاز به دقت عددی دارند مفید است.
- رسیدگی به رویداد: این مؤلفه از رویدادهای صفحه کلید (OnkeyDown) و Change (OnChange) استفاده می کند تا اطمینان حاصل شود که ورودی کاربر در زمان واقعی تأیید شده و فرمت شده است.
منطق / قالب بندی ارزش مؤلفه
عملکرد FormatValue هسته اصلی مؤلفه است. این مقدار با توجه به قوانین تعریف شده ، مقدار وارد شده توسط کاربر را قالب بندی می کند. در اینجا تفکیک آنچه انجام می دهد آورده شده است:
-
حذف شخصیت های نامعتبر: از یک عبارت معمولی برای حذف هر شخصیتی که رقمی نباشد ، یک علامت به علاوه یا منهای یا جداکننده اعشاری استفاده می کند.
let formatted = input.replace(/[^\d-+,.]/, "")
-
رسیدگی به علائم منفی و مثبت: این تضمین می کند که علامت منفی به درستی قرار گرفته و علائم مثبت بر مقدار نهایی تأثیر نمی گذارد.
if (formatted.includes("-")) {
formatted = formatted.replace(/-/g, "")
formatted = formatted.startsWith("-") ? formatted : `-${formatted}`
}
- دست زدن به جداکننده های اعشاری: این هر جداکننده اعشاری (نقطه یا کاما) را به یک نقطه اعشاری استاندارد تبدیل می کند و تعداد رقم های اعشاری را بر اساس دقت تعریف شده محدود می کند.
if (formatted.includes(".") || formatted.includes(",")) {
formatted = formatted.replace(".", DECIMAL_SEPARATOR)
formatted = formatted.replace(",", DECIMAL_SEPARATOR)
const [intPart, ...rest] = formatted.split(DECIMAL_SEPARATOR)
const decPart = rest.join("")
const limitedDecPart = decPart.slice(0, decimalPrecision.decimalDigits)
const formattedIntPart = !intPart || intPart === "-" ? `0${intPart}` : intPart
formatted = `${formattedIntPart}${DECIMAL_SEPARATOR}${limitedDecPart}`
}
- محدود کردن رقم های عدد صحیح: این تعداد رقم های عدد صحیح را که می توانند وارد شوند ، محدود می کند و اطمینان حاصل می کند که از حد تعریف شده تجاوز نمی کند.
const isNegative = formatted.startsWith("-")
const digits = isNegative ? formatted.slice(1) : formatted
if (digits.length > decimalPrecision.integerDigits) {
formatted = isNegative
? `-${digits.slice(0, decimalPrecision.integerDigits)}`
: digits.slice(0, decimalPrecision.integerDigits)
}
رسیدگی به رویداد صفحه کلید
در عکسبرداری عملکرد تضمین می کند که فقط کلیدهای خاص مربوط به ورودی عددی مجاز هستند. این شامل کلیدهای ناوبری (مانند فلش های چپ و راست) ، کلیدهای ویرایش (مانند فضای پشتی و حذف) و شخصیت های عددی است. اگر کاربر سعی کند یک شخصیت مجاز را وارد کند ، از این رویداد جلوگیری می شود و شخصیت در قسمت ورودی ظاهر نمی شود.
const handleKeyDown = (e: React.KeyboardEvent) => {
const allowedKeys = [
"Backspace", "Delete", "ArrowLeft", "ArrowRight",
"Tab", "Home", "End", "-", "+", ".", ",", "0",
"1", "2", "3", "4", "5", "6", "7", "8", "9"
]
if (!allowedKeys.includes(e.key)) {
e.preventDefault()
} else if (valueInput.includes(DECIMAL_SEPARATOR) && (e.key === "." || e.key === ",")) {
e.preventDefault()
}
}
تغییر دست زدن
در تغییر مغازه عملکرد هر زمان که کاربر مقدار قسمت ورودی را اصلاح کند ، ایجاد می شود. این عملکرد تماس می گیرد با فرمت برای قالب بندی مقدار وارد شده و سپس حالت مؤلفه را با مقدار فرمت شده به روز می کند. علاوه بر این ، آن را به مؤلفه والدین اطلاع می دهد (از طریق مبادله کردن مقدار جدید ، امکان ادغام یکپارچه با سایر مؤلفه ها را فراهم می کند.
const handleChange = (e: React.ChangeEvent) => {
const newValue = formatValue(e.target.value)
setValueInput(newValue)
onChange?.(newValue === '' ? null : newValue)
}
افزایش تجربه کاربر
مؤلفه CustomNumberInput برای بهبود تجربه کاربر هنگام وارد کردن شماره ها در یک برنامه ایجاد شده است. با استفاده از اعتبار سنجی و قالب بندی به طور خودکار ، بار شناختی را روی کاربر کاهش می دهد و خطاهای ورودی را به حداقل می رساند. این امر به ویژه در زمینه مالی ، علمی یا هر زمینه دیگری مفید است که دقت عددی بسیار مهم باشد.
می توانید تعداد رقم های عدد صحیح و اعشاری مجاز را تنظیم کنید و می توانید عملکرد آن را متناسب با نیازهای خاص گسترش دهید.
من به پیشنهادات و پیشرفت های این مؤلفه باز هستم. اگر ایده یا بازخورد دارید ، احساس راحتی کنید که آنها را به اشتراک بگذارید!.
رمز کامل
در اینجا کد کامل برای مؤلفه CustomNumberInput آمده است:
import * as React from "react"
import { type ClassValue, clsx } from "clsx";
import { twMerge } from "tailwind-merge";
type DecimalPrecision = {
integerDigits: number
decimalDigits: number
}
export interface CustomNumberInputProps
extends Omit, 'onChange'> {
className?: string,
decimalPrecision?: DecimalPrecision
onChange?: (value: string | null) => void
}
const DEFAULT_PRECISION: DecimalPrecision = {
integerDigits: 10,
decimalDigits: 2
}
const DECIMAL_SEPARATOR = "."
const CustomNumberInput = React.forwardRef(
({
className,
decimalPrecision = DEFAULT_PRECISION,
onChange,
...props
}, ref) => {
const [valueInput, setValueInput] = React.useState("")
const formatValue = React.useCallback((input: string): string => {
let formatted = input.replace(/[^\d-+,.]/, "")
if (formatted.includes("-")) {
formatted = formatted.replace(/-/g, "")
formatted = formatted.startsWith("-") ? formatted : `-${formatted}`
}
if (formatted.includes("+")) {
formatted = formatted.replace(/-/g, "")
formatted = formatted.replace(/\+/g, "")
}
if (formatted.includes(".") || formatted.includes(",")) {
formatted = formatted.replace(".", DECIMAL_SEPARATOR)
formatted = formatted.replace(",", DECIMAL_SEPARATOR)
const [intPart, ...rest] = formatted.split(DECIMAL_SEPARATOR)
const decPart = rest.join("")
const limitedDecPart = decPart.slice(0, decimalPrecision.decimalDigits)
const formattedIntPart = !intPart || intPart === "-" ? `0${intPart}` : intPart
formatted = `${formattedIntPart}${DECIMAL_SEPARATOR}${limitedDecPart}`
} else {
const isNegative = formatted.startsWith("-")
const digits = isNegative ? formatted.slice(1) : formatted
if (digits.length > decimalPrecision.integerDigits) {
formatted = isNegative
? `-${digits.slice(0, decimalPrecision.integerDigits)}`
: digits.slice(0, decimalPrecision.integerDigits)
}
}
return formatted
}, [decimalPrecision])
const handleKeyDown = (e: React.KeyboardEvent) => {
const allowedKeys = [
"Backspace", "Delete", "ArrowLeft", "ArrowRight",
"Tab", "Home", "End", "-", "+", ".", ",", "0",
"1", "2", "3", "4", "5", "6", "7", "8", "9"
]
if (!allowedKeys.includes(e.key)) {
e.preventDefault()
} else if (valueInput.includes(DECIMAL_SEPARATOR) && (e.key === "." || e.key === ",")) {
e.preventDefault()
}
}
const handleChange = (e: React.ChangeEvent) => {
const newValue = formatValue(e.target.value)
setValueInput(newValue)
onChange?.(newValue === '' ? null : newValue)
}
const cn = (...inputs: ClassValue[]) => {
return twMerge(clsx(inputs));
}
return (
)
}
)
CustomNumberInput.displayName = "CustomNumberInput"
export { CustomNumberInput }