Использование Cleave.js в проектах на jQuery базируется на сочетании императивного подхода DOM-манипуляций и декларативной конфигурации форматирования ввода. Библиотека Cleave.js работает независимо от фреймворков, что делает её совместимой с jQuery, однако требует явного управления экземплярами форматтера при инициализации, обновлении и уничтожении.
Ключевая особенность интеграции заключается в том, что jQuery отвечает за выбор и управление DOM-элементами, тогда как Cleave.js — за поведение форматирования значений ввода.
Типовой сценарий предполагает привязку Cleave.js к input-полям после загрузки DOM:
$(document).ready(function () {
const phoneInput = document.querySelector('.js-phone');
const cleavePhone = new Cleave(phoneInput, {
phone: true,
phoneRegionCode: 'RU'
});
});
В jQuery-ориентированном коде часто используется гибридный стиль:
$(function () {
$('.js-phone').each(function () {
new Cleave(this, {
phone: true,
phoneRegionCode: 'RU'
});
});
});
Такой подход обеспечивает поддержку множественных полей без
необходимости ручного перебора через querySelectorAll.
Cleave.js предоставляет встроенные пресеты для чисел, валют и разделителей разрядов, которые особенно часто используются в формах ввода.
$('.js-price').each(function () {
new Cleave(this, {
numeral: true,
numeralThousandsGroupStyle: 'thousand',
numeralDecimalMark: '.',
delimiter: ' '
});
});
В jQuery-проектах это часто применяется для динамически генерируемых таблиц, где строки добавляются через AJAX или шаблоны:
function initPriceInputs(context) {
$(context).find('.js-price').each(function () {
new Cleave(this, {
numeral: true,
numeralThousandsGroupStyle: 'thousand'
});
});
}
$(document).on('ajaxComplete', function () {
initPriceInputs(document);
});
jQuery активно используется в сценариях с динамическим добавлением элементов. Cleave.js не отслеживает DOM автоматически, поэтому инициализация выполняется вручную после вставки элементов.
$('#add-row').on('click', function () {
const row = `
<div class="row">
<input type="text" class="js-card">
</div>
`;
$('#container').append(row);
const input = $('#container .js-card').last()[0];
new Cleave(input, {
creditCard: true
});
});
Особенность подхода заключается в необходимости получать DOM-узел из
jQuery-объекта через [0], поскольку Cleave.js не принимает
jQuery-wrappers.
В крупных проектах интеграция упрощается через создание собственного jQuery-плагина-обёртки.
(function ($) {
$.fn.cleaveInit = function (options) {
return this.each(function () {
if (!this._cleave) {
this._cleave = new Cleave(this, options);
}
});
};
})(jQuery);
Использование:
$('.js-date').cleaveInit({
date: true,
datePattern: ['d', 'm', 'Y']
});
Подобная обёртка решает сразу несколько задач:
При использовании jQuery важно учитывать жизненный цикл DOM-элементов. Cleave.js создаёт внутреннее состояние, которое должно корректно удаляться при уничтожении элементов.
Типовой паттерн хранения экземпляра:
$('.js-phone').each(function () {
this.cleaveInstance = new Cleave(this, {
phone: true,
phoneRegionCode: 'US'
});
});
Удаление при уничтожении элемента:
function destroyCleave(context) {
$(context).find('input').each(function () {
if (this.cleaveInstance) {
this.cleaveInstance.destroy();
this.cleaveInstance = null;
}
});
}
Такой подход критичен в интерфейсах с модальными окнами, вкладками и динамическими компонентами, где DOM пересоздаётся.
jQuery часто использует делегирование событий:
$(document).on('focus', '.js-input', function () {
// логика
});
Однако Cleave.js не поддерживает ленивую инициализацию через делегирование. Экземпляр должен быть создан на конкретном DOM-узле, поэтому комбинация выглядит следующим образом:
$(document).on('focus', '.js-credit-card', function () {
if (!this.cleaveInstance) {
this.cleaveInstance = new Cleave(this, {
creditCard: true
});
}
});
Такой подход позволяет отложить инициализацию до первого взаимодействия, снижая нагрузку при рендере больших форм.
Cleave.js поддерживает обновление параметров через
setRawValue и пересоздание экземпляра. В jQuery-контексте
часто используется пересоздание:
function updateFormat($input, options) {
const el = $input[0];
if (el.cleaveInstance) {
el.cleaveInstance.destroy();
}
el.cleaveInstance = new Cleave(el, options);
}
Пример применения при смене типа ввода:
$('#type-select').on('change', function () {
const type = $(this).val();
updateFormat($('.js-dynamic-input'), {
numeral: type === 'number',
phone: type === 'phone'
});
});
В jQuery-проектах часто применяется декларативная настройка через HTML:
<input class="js-cleave" data-type="date" data-format="d-m-Y">
Инициализация:
$('.js-cleave').each(function () {
const $el = $(this);
const type = $el.data('type');
const format = $el.data('format');
const options = {};
if (type === 'date') {
options.date = true;
options.datePattern = format.split('-');
}
new Cleave(this, options);
});
Такой подход упрощает интеграцию в серверные шаблонизаторы и legacy-архитектуры, где JavaScript не должен содержать бизнес-логики.
Cleave.js часто используется совместно с jQuery Validation или кастомными валидаторами. Важно учитывать, что Cleave изменяет отображаемое значение, но не всегда влияет на raw value напрямую.
$('form').on('submit', function () {
$('.js-phone').each(function () {
console.log(this.value); // форматированное значение
console.log(this._cleave.getRawValue()); // чистое значение
});
});
Валидационные сценарии часто требуют использования
getRawValue() для корректной обработки данных перед
отправкой.
В интерфейсах с большим количеством полей (например, CRM-формы) важно минимизировать количество активных экземпляров Cleave.js.
Оптимизированный паттерн:
const cleaveMap = new WeakMap();
$('.js-field').each(function () {
const instance = new Cleave(this, {
numeral: true
});
cleaveMap.set(this, instance);
});
Преимущество WeakMap заключается в автоматическом освобождении памяти при удалении DOM-элементов.
В jQuery-архитектуре AJAX часто используется для подгрузки форм:
$('#load-form').on('click', function () {
$('#form-container').load('/form.html', function () {
$('#form-container .js-cleave').each(function () {
new Cleave(this, {
creditCard: true
});
});
});
});
Такая схема обеспечивает корректную инициализацию после каждого обновления контента без глобального пересоздания логики страницы.
В проектах с jQuery Cleave.js обычно включается в один из следующих подходов:
1. Централизованная инициализация
function initCleave(root) {
$(root).find('.js-cleave').each(function () {
new Cleave(this, {
numeral: true
});
});
}
2. Ленивое создание экземпляров
Инициализация по событию фокуса или изменения состояния интерфейса.
3. Плагин-ориентированная архитектура
Инкапсуляция логики в $.fn, что позволяет использовать
библиотеку как часть цепочек jQuery.
jQuery может заменять элементы через .html(),
.replaceWith() и другие методы, что приводит к потере
экземпляров Cleave.js. Поэтому любые DOM-манипуляции требуют повторной
инициализации форматтера:
$('#container').html(newContent);
initCleave('#container');
Игнорирование этого аспекта приводит к рассинхронизации UI и внутреннего состояния библиотеки.
С точки зрения архитектуры, Cleave.js в jQuery-проектах функционирует как слой поведения над DOM-инпутами, полностью управляемый жизненным циклом элементов. jQuery отвечает за выбор, вставку и удаление узлов, тогда как Cleave.js — за форматирование и интерпретацию вводимых данных.