sanitize —— санитизация чисел
Номер страницы, интервал, step, precision, предельный размер — множество функций слоя core принимают числа извне. Стоит NaN / Infinity попасть внутрь, и они загрязняют всё дальше по цепочке: стили NaNpx, пустой массив из slice(NaN), RangeError из toFixed(1000), ломающий рендеринг. Стратегия этого модуля — перехватывать в одной точке входа, чтобы алгоритмы downstream работали только с «уже чистыми» числами.
import { sanitizeNumber, clamp, safePrecision, LH_PRECISION_MAX, type LhSanitizeNumberOptions,} from '@lh-ui/share/core/shared/sanitize'Типы и константы
Заголовок раздела «Типы и константы»export interface LhSanitizeNumberOptions { min?: number // допустимый минимум (нефинитный min игнорируется) max?: number // допустимый максимум (нефинитный max игнорируется) integer?: boolean // округлять ли до целого (отбрасыванием дробной части)}
export const LH_PRECISION_MAX = 100 // верхний предел precision: toFixed больше 100 бросает RangeErrorТаблица функций
Заголовок раздела «Таблица функций»| Функция | Сигнатура | Назначение |
|---|---|---|
sanitizeNumber |
(value: number | undefined | null, fallback: number, options?) => number |
превратить любое значение в конечное число |
clamp |
(value: number, min: number, max: number) => number |
исходный кламп, без всякой санитизации |
safePrecision |
(precision: number) => number |
санитизирует precision в целое из [0, 100] |
sanitizeNumber
Заголовок раздела «sanitizeNumber»sanitizeNumber(5, 0) // 5sanitizeNumber(NaN, 0) // 0sanitizeNumber(Infinity, 10) // 10sanitizeNumber(undefined, 1) // 1sanitizeNumber(null, 1) // 1sanitizeNumber(3.7, 0, { integer: true }) // 3 (отбрасыванием, а не округлением)sanitizeNumber(-5, 0, { min: 0 }) // 0sanitizeNumber(999, 0, { max: 100 }) // 100Порядок обработки: проверка на нефинитность → округление integer → кламп по min → кламп по max.
Ключевое решение: min / max тоже проходят фильтрацию на нефинитность.
sanitizeNumber(5, 0, { min: NaN, max: Infinity })// 5 —— плохой min/max не вернёт NaN в результатПочему это важно: min / max обычно приходят из props пользователя (<lh-slider :min="NaN">); если их не фильтровать, Math.max(NaN, 5) даст NaN — санитизация окажется бессмысленной.
clamp(12, 0, 10) // 10clamp(-3, 0, 10) // 0clamp(5, 0, 10) // 5clamp(NaN, 0, 10) // NaN —— проходит насквозь!clamp — это простой Math.min(Math.max(value, min), max) без санитизации. Это сделано намеренно:
- В сценариях, где вызывающая сторона уже гарантирует конечность, не нужна повторная санитизация:
clampValueв input-number, кламп перетаскивания в slider, геометрический кламп в popper — всё из этого ряда (значения приходят из собственных промежуточных вычислений). - Сохраняется семантика прозрачного прохода NaN: в некоторых сценариях нужно, чтобы «NaN остался NaN» вплоть до граничной проверки; единое поглощение скрыло бы баг.
Принцип выбора: значение пришло извне (props, пользовательский ввод, сеть) → sanitizeNumber; значение получено внутренним вычислением → clamp.
safePrecision
Заголовок раздела «safePrecision»safePrecision(2) // 2safePrecision(-1) // 0safePrecision(999) // 100safePrecision(NaN) // 0safePrecision(2.7) // 2 (сначала округление)Эквивалентно sanitizeNumber(precision, 0, { min: 0, max: LH_PRECISION_MAX, integer: true }).
Почему санитизация обязательна: (1.234).toFixed(precision) при precision > 100 бросает RangeError — один некорректный проп precision напрямую рендерит input-number / statistic неработоспособными. Санитизация в 0 намного лучше сломанного рендеринга.
Кто использует
Заголовок раздела «Кто использует»| Потребитель | Применение |
|---|---|
pagination |
sanitizeNumber(currentPage, 1, { min: 1 }) |
input-number |
sanitizeNumber(props.step, 1, { min: 0 }) + safePrecision(props.precision) |
space |
sanitizeNumber(props.size, 8) (интервал) |
popper |
санитизация полей rect + кламп |
keyboard |
clamp для навигационных границ |
statistic |
safePrecision(props.precision) |
Примеры использования
Заголовок раздела «Примеры использования»Санитизация props
Заголовок раздела «Санитизация props»// компонент paginationconst currentPage = computed(() => sanitizeNumber(props.currentPage, 1, { min: 1, max: totalPages.value }),)Защитная утилита
Заголовок раздела «Защитная утилита»// санитизация значения, извлечённого из событияconst value = sanitizeNumber(Number(e.target.value), 0)Безопасный precision
Заголовок раздела «Безопасный precision»const display = modelValue.value.toFixed(safePrecision(props.precision))Замечания
Заголовок раздела «Замечания»integer— это отбрасывание дробной части (Math.trunc), а не округление:3.7 → 3,-3.7 → -3. Для сценариев вроде пагинации и индексов нужно именно отбрасывание.clampне санитизирует: это свойство, а не баг; не «исправляйте» его на санитизирующий (это сломает отладочную ценность прозрачного прохода NaN).fallbackобязателен: универсального значения по умолчанию нет («безопасное значение» в разных сценариях своё), и обязательная передача заставляет вызывающую сторону задуматься.
@lh-ui/share/core/sanitize → sanitizeNumber( )(填好参数后点运行)Copyright © 2024-2026 FengMo WenXue