Применение в jQuery-проектах

Использование Cleave.js в проектах на jQuery базируется на сочетании императивного подхода DOM-манипуляций и декларативной конфигурации форматирования ввода. Библиотека Cleave.js работает независимо от фреймворков, что делает её совместимой с jQuery, однако требует явного управления экземплярами форматтера при инициализации, обновлении и уничтожении.

Ключевая особенность интеграции заключается в том, что jQuery отвечает за выбор и управление DOM-элементами, тогда как Cleave.js — за поведение форматирования значений ввода.


Базовая инициализация через jQuery

Типовой сценарий предполагает привязку 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);
});

Работа с динамическими элементами DOM

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.


Обёртка Cleave.js как jQuery-плагина

В крупных проектах интеграция упрощается через создание собственного 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']
});

Подобная обёртка решает сразу несколько задач:

  • предотвращает повторную инициализацию
  • сохраняет ссылку на экземпляр
  • упрощает массовое применение конфигурации

Управление экземплярами Cleave.js

При использовании 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
        });
    }
});

Такой подход позволяет отложить инициализацию до первого взаимодействия, снижая нагрузку при рендере больших форм.


Обновление конфигурации через jQuery

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'
    });
});

Использование data-атрибутов для конфигурации

В 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 не должен содержать бизнес-логики.


Интеграция с формами и валидацией jQuery

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-элементов.


Совместимость с AJAX-рендерингом

В 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.


Особенности взаимодействия с DOM-обновлениями

jQuery может заменять элементы через .html(), .replaceWith() и другие методы, что приводит к потере экземпляров Cleave.js. Поэтому любые DOM-манипуляции требуют повторной инициализации форматтера:

$('#container').html(newContent);

initCleave('#container');

Игнорирование этого аспекта приводит к рассинхронизации UI и внутреннего состояния библиотеки.


Итоговая модель интеграции

С точки зрения архитектуры, Cleave.js в jQuery-проектах функционирует как слой поведения над DOM-инпутами, полностью управляемый жизненным циклом элементов. jQuery отвечает за выбор, вставку и удаление узлов, тогда как Cleave.js — за форматирование и интерпретацию вводимых данных.