В браузерных приложениях значение поля ввода может изменяться не
только через действия пользователя или API самой библиотеки, но и извне:
через прямое присваивание input.value, через сторонние
скрипты, через реактивные фреймворки, через обновление DOM после
AJAX-запросов. В таких сценариях возникает проблема рассинхронизации:
форматтер чисел перестаёт соответствовать реальному значению поля.
Поведение, связанное с наблюдением за внешними изменениями, в AutoNumeric решает задачу постоянного поддержания согласованного состояния между «сырым» значением DOM и внутренним представлением библиотеки.
AutoNumeric поддерживает механизм, который отслеживает изменения значения input-элемента, происходящие не через его собственные методы установки значения.
Когда включён режим наблюдения за внешними изменениями, библиотека:
value извне;Таким образом, даже если значение изменено сторонним кодом напрямую, AutoNumeric восстанавливает корректный формат.
Сценарии, в которых возникает необходимость наблюдения:
const input = document.querySelector("#price");
input.value = "1234567.89";
Без механизма наблюдения библиотека может не отреагировать на такое изменение.
fetch("/api/price")
.then(r => r.json())
.then(data => {
input.value = data.price;
});
Значение меняется вне контекста AutoNumeric.
Vue, React (через uncontrolled inputs), Angular или Svelte могут изменять DOM при ререндере.
state.price = 99999;
Если библиотека не отслеживает изменения DOM напрямую, форматирование нарушается.
document.querySelectorAll(".price").forEach(el => {
el.value = "1000";
});
При большом количестве полей необходимость синхронизации становится критичной.
В AutoNumeric это поведение задаётся через конфигурационный параметр
watchExternalChanges.
const anElement = new AutoNumeric("#price", {
watchExternalChanges: true
});
При включении параметра библиотека начинает отслеживать любые
изменения value, не инициированные её собственными
методами.
Когда внешний код меняет input.value, происходит
следующий цикл:
Если значение некорректно, поведение зависит от дополнительных опций (например, очистка, нормализация или откат).
AutoNumeric различает два типа изменений:
set(),
setNumericString(), upd ate();watchExternalChanges реагирует только на второй тип.
anElement.se t(1000); // внутреннее изменение
input.value = 2000; // внешнее изменение
В первом случае повторная обработка не требуется, во втором — запускается синхронизация.
При частых внешних изменениях (например, в циклах или при анимациях) возможны частые переформатирования:
setInterval(() => {
input.value = Math.random() * 10000;
}, 50);
Это может привести к дополнительной нагрузке из-за постоянного парсинга и форматирования.
В некоторых архитектурах (особенно Vue/React с controlled inputs) происходит двойное управление значением:
Это может приводить к эффекту «дёрганья» значения.
При внешнем обновлении значения поле может терять позицию каретки, так как DOM-значение полностью перезаписывается форматированным результатом.
Включение watchExternalChanges целесообразно только там,
где есть реальные внешние источники изменений.
const anElement = new AutoNumeric("#price", {
watchExternalChanges: false
});
Вместо:
input.value = 5000;
предпочтительно:
anElement.set(5000);
Это исключает необходимость внешнего наблюдения.
При массовых изменениях полезно минимизировать количество перерисовок:
const values = [100, 200, 300];
values.forEach(v => anElement.set(v));
Либо использовать временное отключение логики обновления (через уничтожение и повторную инициализацию экземпляра в сложных случаях).
В некоторых реализациях наблюдение может быть реализовано через
MutationObserver, отслеживающий изменения атрибута
value.
Логика обычно включает:
value;Ключевая инженерная проблема — избежать ситуации:
value;Для предотвращения используется внутренний флаг состояния:
Только внешние изменения запускают повторную обработку.
const price = new AutoNumeric("#price", {
decimalPlaces: 2,
digitGroupSeparator: " ",
decimalCharacter: ".",
watchExternalChanges: true
});
// внешняя система обновляет данные
function updateFromServer(value) {
document.querySelector("#price").value = value;
}
// симуляция обновлений
setTimeout(() => updateFromServer("12345.6"), 1000);
setTimeout(() => updateFromServer("987654.321"), 2000);
Каждое внешнее обновление автоматически приводит к:
12 345.60,
987 654.32.Стоимость включённого наблюдения зависит от:
При десятках и сотнях полей с активным наблюдением нагрузка возрастает линейно. Особенно заметно это в таблицах с динамическими значениями.
В системах, где данные часто приходят извне, более стабильной является модель:
Такой подход снижает необходимость постоянного DOM-слежения и уменьшает вероятность рассинхронизации состояния.
При вызове destroy() наблюдение за внешними изменениями
прекращается. DOM-элемент возвращается к стандартному поведению input,
без автоматического форматирования.
anElement.destroy();
После этого любые изменения input.value больше не
обрабатываются библиотекой.