Интеграция с Vue.js

Библиотека Inputmask подключается в Vue-проекты как обычный npm-пакет и используется либо через директивы, либо через программное применение к DOM-элементам после монтирования компонента. В современных версиях Vue (Vue 3) предпочтение отдаётся директивному подходу или composable-обёрткам, обеспечивающим реактивное обновление маски.

Базовая установка:

npm install inputmask

После установки доступен импорт:

import Inputmask from "inputmask";

Применение Inputmask в Vue через директиву

Директивный подход обеспечивает наиболее чистую интеграцию с шаблонами Vue и позволяет автоматически управлять жизненным циклом маски.

Простейшая реализация директивы:

// directives/mask.js
import Inputmask from "inputmask";

export default {
  mounted(el, binding) {
    Inputmask(binding.value).mask(el);
  },
  updated(el, binding) {
    if (binding.value !== binding.oldValue) {
      Inputmask.remove(el);
      Inputmask(binding.value).mask(el);
    }
  },
  unmounted(el) {
    Inputmask.remove(el);
  }
};

Регистрация глобально:

import { createApp } from "vue";
import App from "./App.vue";
import mask from "./directives/mask";

const app = createApp(App);
app.directive("mask", mask);
app.mount("#app");

Использование в шаблоне:

<input v-mask="{ mask: '+7 (999) 999-99-99' }" />

Реактивные маски и работа с динамическими значениями

В Vue часто требуется изменять маску в зависимости от состояния формы. Inputmask поддерживает полную пересборку конфигурации.

Ключевая особенность заключается в необходимости пересоздания маски при изменении параметров:

updated(el, binding) {
  const changed = JSON.stringify(binding.value) !== JSON.stringify(binding.oldValue);

  if (changed) {
    Inputmask.remove(el);
    Inputmask(binding.value).mask(el);
  }
}

Типичный сценарий — переключение страны:

<sel ect v-model="country">
  <option value="ru">RU</option>
  <option value="us">US</option>
</select>

<input v-mask="maskConfig" />
computed: {
  maskConfig() {
    return this.country === "ru"
      ? { mask: "+7 (999) 999-99-99" }
      : { mask: "+1 (999) 999-9999" };
  }
}

Интеграция через Composition API

Composition API позволяет более гибко управлять жизненным циклом маски и реактивными зависимостями.

import { ref, watch, onMounted, onBeforeUnmount } fr om "vue";
import Inputmask from "inputmask";

export function useMask(maskOptions, inputRef) {
  let im = null;

  const applyMask = () => {
    if (!inputRef.value) return;

    if (im) {
      im.remove();
    }

    im = new Inputmask(maskOptions.value);
    im.mask(inputRef.value);
  };

  onMounted(applyMask);

  watch(maskOptions, () => {
    applyMask();
  }, { deep: true });

  onBeforeUnmount(() => {
    if (im && inputRef.value) {
      im.remove();
    }
  });
}

Использование:

const input = ref(null);

const maskOptions = ref({
  mask: "9999-9999-9999-9999"
});

useMask(maskOptions, input);
<input ref="input" />

Работа с v-model и синхронизация значения

Inputmask изменяет отображаемое значение, но Vue должен оставаться источником истины. Для этого требуется синхронизация через события ввода.

mounted(el, binding, vnode) {
  const im = Inputmask(binding.value);
  im.mask(el);

  el.addEventListener("input", () => {
    vnode.emit("update:modelValue", el.value);
  });
}

В компоненте:

<MyInput v-model="phone" />

Такой подход предотвращает рассинхронизацию между DOM и реактивным состоянием.

Поддержка Vue 2

В Vue 2 используется аналогичный директивный механизм, но с другими хуками жизненного цикла:

Vue.directive("mask", {
  bind(el, binding) {
    Inputmask(binding.value).mask(el);
  },
  update(el, binding) {
    Inputmask.remove(el);
    Inputmask(binding.value).mask(el);
  },
  unbind(el) {
    Inputmask.remove(el);
  }
});

Особенность Vue 2 заключается в том, что bind и update заменяют mounted и updated, а управление памятью требует более аккуратного удаления маски.

Обработка сложных масок

Inputmask поддерживает маски с алиасами и регулярными выражениями, что удобно при интеграции в Vue-формы.

Пример email-маски:

{ alias: "email" }
<input v-mask="{ alias: 'email' }" />

Для числовых форматов:

{
  alias: "numeric",
  groupSeparator: " ",
  digits: 2,
  digitsOptional: false,
  prefix: "$ "
}

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

Обработка событий и кастомное поведение

Inputmask предоставляет события, которые можно использовать внутри Vue-компонентов:

mounted(el) {
  const im = Inputmask({ mask: "999-999" }).mask(el);

  el.inputmask.on("complete", () => {
    el.classList.add("is-complete");
  });

  el.inputmask.on("incomplete", () => {
    el.classList.remove("is-complete");
  });
}

События позволяют строить сложную логику валидации без участия Vue watchers.

Очистка и предотвращение утечек памяти

При частой смене компонентов или условном рендеринге необходимо гарантировать удаление маски:

onBeforeUnmount(() => {
  if (inputRef.value) {
    Inputmask.remove(inputRef.value);
  }
});

Игнорирование этого шага приводит к накоплению обработчиков событий и некорректной работе input-элементов при повторном монтировании.

SSR и особенности серверного рендеринга

Inputmask работает только в браузере, поэтому при использовании Nuxt или SSR необходимо ограничивать выполнение:

if (typeof window !== "undefined") {
  Inputmask({ mask: "9999" }).mask(el);
}

Либо использовать клиентские плагины:

export default defineNuxtPlugin(() => {
  if (process.client) {
    // регистрация директив
  }
});

Динамическая генерация масок

Vue-логика позволяет формировать маски на основе данных формы:

computed: {
  dynamicMask() {
    return {
      mask: this.isInternational ? "+999 999 999 999" : "999 999 9999"
    };
  }
}

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

Валидация через Inputmask в Vue-формах

Inputmask не является полноценной системой валидации, но может использоваться как первый уровень контроля.

el.addEventListener("blur", () => {
  if (!el.inputmask.isComplete()) {
    el.setCustomValidity("Некорректный формат");
  } else {
    el.setCustomValidity("");
  }
});

Интеграция с нативной HTML5-валидацией позволяет использовать стандартные механизмы Vue-форм без дополнительных библиотек.

Маскирование с пользовательскими символами

Inputmask поддерживает кастомные определения символов:

{
  mask: "aa-9999",
  definitions: {
    a: {
      validator: "[A-Za-z]",
      casing: "upper"
    }
  }
}

В Vue это особенно полезно при работе с кодами продуктов, артикулов и внутренних идентификаторов.

Управление фокусом и курсором

При работе с масками важно учитывать позицию курсора, особенно при автозаполнении:

el.addEventListener("focus", () => {
  Inputmask.setValue(el, el.value);
});

Поведение курсора напрямую влияет на UX при вводе телефонных номеров и дат.

Итоговая архитектура интеграции

Типовая структура Vue-приложения с Inputmask включает:

  • директиву v-mask для шаблонного применения
  • composable useMask для реактивных сценариев
  • централизованную конфигурацию масок
  • обработку событий complete/incomplete
  • защиту от SSR-ошибок
  • обязательное удаление маски при размонтировании

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