Кастомные элементы - Custom Elements в современном JavaScript

28 января 2026
Автор

Олег Марков

Введение

Кастомные элементы (Custom Elements) — это часть стандарта Web Components, которая позволяет вам определять собственные HTML‑теги с предсказуемым поведением и повторно использовать их в разных проектах.

Идея простая: вы описываете новый элемент один раз, а потом можете использовать его как обычный тег в любом месте страницы или даже в других приложениях. Например, вместо очередного набора div с классами вы пишете:

<user-card name="Alice" status="online"></user-card>

и получаете готовый компонент с разметкой, стилями и логикой внутри.

Здесь мы разберём, как это работает:

  • какие есть виды кастомных элементов;
  • как их регистрировать через customElements.define;
  • какие есть жизненные циклы (колбэки) и когда они вызываются;
  • как связать кастомный элемент с Shadow DOM;
  • как передавать данные через атрибуты и свойства;
  • как проектировать компоненты так, чтобы ими было удобно пользоваться и поддерживать.

Давайте начнём с базовых понятий и постепенно перейдём к более практичным примерам.


Что такое кастомные элементы и как они вписываются в Web Components

Связь с Web Components

Кастомные элементы — это один из трёх основных блоков Web Components:

  1. Custom Elements — определение собственных тегов и их поведения на JavaScript.
  2. Shadow DOM — инкапсуляция разметки и стилей внутри компонента.
  3. HTML Templates — шаблоны разметки, которые можно копировать и наполнять данными.

Смотрите, важный момент: для использования кастомных элементов не обязательно подключать Shadow DOM или шаблоны, но чаще всего они используются вместе. Это помогает сделать компонент независимым и менее конфликтным с остальной страницей.

Требования к имени кастомного элемента

По стандарту любой кастомный элемент:

  • должен иметь дефис в имени, например user-card, app-button, x-modal;
  • не может использовать уже зарезервированные браузером теги;
  • регистрируется только один раз в пределах документа (попытка повторной регистрации вызовет ошибку).

Дефис — это способ браузера отличить кастомный элемент от встроенного, даже если их список будет расширяться в будущем.


Базовая регистрация кастомного элемента

Класс элемента и customElements.define

Любой кастомный элемент — это класс, который наследуется от HTMLElement (или от другого HTML‑класса при использовании встроенных элементов).

Давайте разберём минимальный пример:

// Определяем класс кастомного элемента
class HelloWorld extends HTMLElement {
  constructor() {
    super(); // Вызываем конструктор родительского класса HTMLElement

    // Здесь пока просто добавим текстовый узел
    this.textContent = 'Привет из кастомного элемента';
  }
}

// Регистрируем новый тег <hello-world> в глобальном реестре
customElements.define('hello-world', HelloWorld);

Теперь этот элемент можно использовать в HTML:

<hello-world></hello-world>

Как видите, базовый сценарий довольно простой: класс + customElements.define.

Устройство customElements

Объект customElements — это реестр всех зарегистрированных в документе кастомных элементов. Он предоставляет несколько методов:

  • define(name, constructor, options?) — регистрация элемента;
  • get(name) — получить конструктор по имени;
  • whenDefined(name) — вернуть промис, который зарезолвится, когда элемент будет определён.

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


Жизненный цикл кастомного элемента

Основные колбэки

У кастомных элементов есть несколько специальных методов, которые браузер вызывает в определённые моменты жизни элемента:

  • constructor — когда элемент создаётся (но ещё не обязательно вставлен в DOM);
  • connectedCallback — когда элемент добавлен в документ (вставлен в DOM);
  • disconnectedCallback — когда элемент удалён из документа;
  • attributeChangedCallback(name, oldValue, newValue) — когда меняется наблюдаемый атрибут;
  • adoptedCallback — когда элемент перенесён в другой документ (редко используемый кейс, например в iframe).

Давайте посмотрим пример, где используются основные из них.

class LoggerElement extends HTMLElement {
  constructor() {
    super();
    // Здесь можно подготовить внутреннее состояние
    console.log('constructor: элемент создан');
  }

  connectedCallback() {
    // Вызывается, когда элемент добавлен в DOM
    console.log('connectedCallback: элемент добавлен в документ');
    this.textContent = 'Элемент сейчас в DOM';
  }

  disconnectedCallback() {
    // Вызывается, когда элемент удалён из DOM
    console.log('disconnectedCallback: элемент удален из документа');
  }

  static get observedAttributes() {
    // Здесь перечисляем имена атрибутов, за которыми хотим следить
    return ['status'];
  }

  attributeChangedCallback(name, oldValue, newValue) {
    // Вызывается каждый раз, когда меняется один из observedAttributes
    console.log(
      `attributeChangedCallback: атрибут ${name} изменился с ${oldValue} на ${newValue}`
    );

    if (name === 'status') {
      // Здесь можно обновить текст или стили на основе нового значения
      this.textContent = `Текущий статус - ${newValue}`;
    }
  }
}

customElements.define('logger-element', LoggerElement);

Теперь вы увидите, как это выглядит в HTML:

<logger-element status="active"></logger-element>

<script>
  // Меняем атрибут через 2 секунды
  setTimeout(() => {
    const el = document.querySelector('logger-element');
    // Здесь обновляем атрибут, что вызовет attributeChangedCallback
    el.setAttribute('status', 'offline');
  }, 2000);
</script>

Обратите внимание: чтобы attributeChangedCallback работал, нужно объявить static get observedAttributes(). Без этого колбэк не будет вызываться.


Атрибуты, свойства и связь с DOM

Разница между атрибутами и свойствами

У любого DOM‑элемента есть:

  • атрибуты — то, что вы видите в HTML (<user-card name="Alice">);
  • свойства объекта — то, что вы видите в JavaScript (element.name).

Встроенные элементы обычно синхронизируют некоторые атрибуты и свойства между собой. Например:

// Для <input>
input.value = 'Привет';     // Обновит атрибут value в DOM
input.setAttribute('value', 'Пока'); // Влияет на свойство при следующих рендерах

С кастомными элементами вы сами решаете, как связать атрибуты и свойства.

Передача данных через атрибуты

Давайте создадим компонент, который принимает имя пользователя через атрибут name и показывает его:

class UserCard extends HTMLElement {
  constructor() {
    super();
    // Создаем корневой элемент для контента
    const container = document.createElement('div');
    container.textContent = 'Загрузка...';
    // Добавляем в сам элемент
    this.appendChild(container);
    // Сохраняем ссылку для дальнейших обновлений
    this._container = container;
  }

  static get observedAttributes() {
    // Следим за атрибутом name
    return ['name'];
  }

  attributeChangedCallback(name, oldValue, newValue) {
    // Если изменился атрибут name - обновляем отображение
    if (name === 'name') {
      this._render();
    }
  }

  connectedCallback() {
    // Вызываем рендер при первом добавлении в DOM
    this._render();
  }

  _render() {
    // Берем значение атрибута name
    const name = this.getAttribute('name') || 'Гость';
    this._container.textContent = `Пользователь - ${name}`;
  }
}

customElements.define('user-card', UserCard);

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

<user-card name="Alice"></user-card>
<user-card></user-card> <!-- Выведет "Гость" -->

Теперь давайте посмотрим, как можно связать это с JavaScript‑свойством.

Синхронизация атрибутов и свойств

Часто удобно иметь свойство name, которое под капотом обновляет атрибут:

class UserCard2 extends HTMLElement {
  constructor() {
    super();
    this._container = document.createElement('div');
    this.appendChild(this._container);
  }

  static get observedAttributes() {
    return ['name'];
  }

  // Геттер свойства name
  get name() {
    // Возвращаем значение атрибута
    return this.getAttribute('name');
  }

  // Сеттер свойства name
  set name(value) {
    // Обновляем атрибут - это вызовет attributeChangedCallback
    if (value === null || value === undefined) {
      this.removeAttribute('name');
    } else {
      this.setAttribute('name', String(value));
    }
  }

  attributeChangedCallback(name) {
    if (name === 'name') {
      this._render();
    }
  }

  connectedCallback() {
    this._render();
  }

  _render() {
    const name = this.name || 'Гость'; // Берем значение свойства
    this._container.textContent = `Пользователь - ${name}`;
  }
}

customElements.define('user-card2', UserCard2);

Теперь можно работать с компонентом и так, и так:

const card = document.querySelector('user-card2');

// Меняем через атрибут
card.setAttribute('name', 'Alice');

// Меняем через свойство
card.name = 'Bob';

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


Инкапсуляция через Shadow DOM

Зачем нужен Shadow DOM

Shadow DOM позволяет создать "теневой" корень внутри элемента, где:

  • находятся его собственные узлы DOM;
  • действуют свои стили;
  • внешний CSS не ломает внутреннюю верстку;
  • структуру тени не видно в обычном дереве DOM (в инспекторе DevTools есть отдельный блок).

Это особенно полезно для компонентов, которые должны вести себя одинаково в любом окружении.

Создание Shadow DOM

Теперь вы увидите, как это выглядит в коде:

class FancyButton extends HTMLElement {
  constructor() {
    super();

    // Создаем shadow root в "закрытом" режиме
    const shadow = this.attachShadow({ mode: 'open' });
    // Если используете 'closed' - к shadow нельзя будет обратиться извне через element.shadowRoot

    // Создаем стили
    const style = document.createElement('style');
    style.textContent = `
      button {
        padding: 8px 16px;
        border-radius: 4px;
        border: none;
        cursor: pointer;
        background-color: #1976d2;
        color: white;
        font-size: 14px;
      }

      button:hover {
        background-color: #1565c0;
      }
    `;

    // Создаем кнопку
    const button = document.createElement('button');
    button.textContent = this.getAttribute('label') || 'Кнопка';

    // Обрабатываем клик
    button.addEventListener('click', () => {
      // Генерируем собственное событие для внешнего мира
      this.dispatchEvent(new CustomEvent('fancy-click', {
        detail: { timestamp: Date.now() },
        bubbles: true,  // Событие поднимается вверх по DOM
        composed: true  // Событие выходит за пределы shadow root
      }));
    });

    // Добавляем стили и кнопку в shadow root
    shadow.appendChild(style);
    shadow.appendChild(button);

    // Сохраняем ссылку, чтобы обновлять текст позже
    this._button = button;
  }

  static get observedAttributes() {
    return ['label'];
  }

  attributeChangedCallback(name, oldValue, newValue) {
    if (name === 'label' && this._button) {
      // Обновляем текст кнопки при изменении атрибута label
      this._button.textContent = newValue;
    }
  }
}

customElements.define('fancy-button', FancyButton);

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

<fancy-button label="Отправить"></fancy-button>

<script>
  const btn = document.querySelector('fancy-button');

  // Слушаем кастомное событие fancy-click
  btn.addEventListener('fancy-click', (event) => {
    // Здесь обрабатываем клик по кастомной кнопке
    console.log('Клик по fancy-button', event.detail);
  });
</script>

Обратите внимание, как этот фрагмент кода решает задачу:

  • стили и разметка спрятаны внутри Shadow DOM;
  • внешний CSS не должен повлиять на кнопку;
  • внешний код работает через события и атрибуты, не зная о деталях реализации.

Слоты и передача контента в компонент

Основная идея слотов

Иногда вам нужно, чтобы компонент отображал не только свою разметку, но и контент, который передаётся из HTML. Для этого используются слоты (<slot>).

Смотрите, я покажу вам, как это работает.

class CardBox extends HTMLElement {
  constructor() {
    super();

    const shadow = this.attachShadow({ mode: 'open' });

    const style = document.createElement('style');
    style.textContent = `
      .card {
        border: 1px solid #ddd;
        border-radius: 6px;
        padding: 12px;
        box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
        background: #fff;
        font-family: sans-serif;
        max-width: 300px;
      }

      .title {
        font-weight: 600;
        margin-bottom: 8px;
      }

      .content {
        font-size: 14px;
        color: #444;
      }
    `;

    const wrapper = document.createElement('div');
    wrapper.className = 'card';

    // Заголовок с именованным слотом title
    const title = document.createElement('div');
    title.className = 'title';
    title.innerHTML = '<slot name="title">Заголовок по умолчанию</slot>';

    // Основной контент со слотом по умолчанию
    const content = document.createElement('div');
    content.className = 'content';
    content.innerHTML = '<slot>Содержимое по умолчанию</slot>';

    wrapper.appendChild(title);
    wrapper.appendChild(content);

    shadow.appendChild(style);
    shadow.appendChild(wrapper);
  }
}

customElements.define('card-box', CardBox);

Теперь давайте разберемся на примере использования:

<card-box>
  <!-- Передаем текст в слот по умолчанию -->
  Здесь основной текст карточки

  <!-- Передаем заголовок в именованный слот title -->
  <span slot="title">Заголовок карточки</span>
</card-box>

Браузер поместит узел span в слот с именем title, а текст "Здесь основной текст…" — в слот по умолчанию.

Если вы ничего не передадите, отобразятся значения по умолчанию, заданные внутри <slot>.


Встроенные (автоматически расширяемые) элементы

Что такое customized built-in elements

Иногда полезно не создавать полностью новый тег, а расширить уже существующий, например <button> или <a>.

Такие элементы называются "customized built-in elements". Они:

  • наследуются от конкретного HTML‑класса, например HTMLButtonElement;
  • регистрируются с опцией extends;
  • используются через атрибут is в HTML.

Покажу вам, как это реализовано на практике.

class DangerButton extends HTMLButtonElement {
  constructor() {
    super();
    // Здесь настраиваем внешний вид и поведение
    this.style.backgroundColor = '#d32f2f';
    this.style.color = '#fff';
    this.style.border = 'none';
    this.style.padding = '6px 12px';

    this.addEventListener('click', () => {
      // При клике выводим подтверждение
      const ok = window.confirm('Вы уверены что хотите выполнить опасное действие');
      if (!ok) {
        // Если отменили, предотвращаем действие
        console.log('Действие отменено пользователем');
      }
    });
  }
}

// Регистрируем кастомизированный встроенный элемент
customElements.define('danger-button', DangerButton, { extends: 'button' });

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

<button is="danger-button">Удалить все</button>

Важно: поддержка customized built-in elements в некоторых браузерах до сих пор ограничена, особенно без флагов. Часто разработчики избегают этого механизма ради кроссбраузерности и используют автономные элементы (<my-button>) с внутренней разметкой.


Стилизация кастомных элементов

Внешние стили и кастомные элементы без Shadow DOM

Если вы не используете Shadow DOM, кастомный элемент ведёт себя как обычный тег:

<user-card name="Alice"></user-card>

<style>
  user-card {
    display: block;
    border: 1px solid #ddd;
    padding: 8px;
  }
</style>

Браузер просто применит задание CSS к этому тегу, как к любому другому.

Стили внутри Shadow DOM

Когда вы используете Shadow DOM, обычные стили снаружи не влияют на внутреннюю разметку. Вся стилизация делается внутри shadow root (как мы уже видели в примерах со style).

Но иногда нужно дать возможность пользователю компонента настраивать внешний вид. Для этого есть несколько механизмов:

  • CSS Custom Properties (переменные) — проходят через границу Shadow DOM;
  • псевдоэлементы и ::part, ::theme (там, где поддерживается).

Использование CSS‑переменных

Смотрите, я размещаю пример, чтобы вам было проще понять:

class ThemeButton extends HTMLElement {
  constructor() {
    super();
    const shadow = this.attachShadow({ mode: 'open' });

    const style = document.createElement('style');
    style.textContent = `
      button {
        padding: 8px 16px;
        border-radius: 4px;
        border: none;
        cursor: pointer;
        /* Используем CSS‑переменные с дефолтными значениями */
        background-color: var(--theme-button-bg, #6200ee);
        color: var(--theme-button-color, #ffffff);
      }
    `;

    const btn = document.createElement('button');
    btn.textContent = this.getAttribute('label') || 'Кнопка';

    shadow.appendChild(style);
    shadow.appendChild(btn);
  }
}

customElements.define('theme-button', ThemeButton);

Теперь вы увидите, как можно влиять на цвета снаружи:

<!-- Используем стили на уровне страницы -->
<style>
  theme-button {
    /* Задаем значения CSS‑переменных для всех theme-button */
    --theme-button-bg: #009688;
    --theme-button-color: #ffffff;
  }

  theme-button.primary {
    --theme-button-bg: #1976d2;
  }

  theme-button.danger {
    --theme-button-bg: #d32f2f;
  }
</style>

<theme-button label="Ок" class="primary"></theme-button>
<theme-button label="Удалить" class="danger"></theme-button>

CSS‑переменные — основной способ "пробросить" тему внутрь Shadow DOM без нарушения инкапсуляции.


Работа с событиями

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

Кастомные элементы особенно полезны, когда вам нужно спрятать сложную логику, но при этом "уведомлять" внешний код о важных действиях.

Для этого обычно используют CustomEvent.

class CounterElement extends HTMLElement {
  constructor() {
    super();
    const shadow = this.attachShadow({ mode: 'open' });

    let value = Number(this.getAttribute('value')) || 0;

    const style = document.createElement('style');
    style.textContent = `
      .counter {
        display: inline-flex;
        gap: 8px;
        align-items: center;
        font-family: sans-serif;
      }
      button {
        padding: 2px 8px;
      }
      span {
        min-width: 20px;
        text-align: center;
      }
    `;

    const wrapper = document.createElement('div');
    wrapper.className = 'counter';

    const decBtn = document.createElement('button');
    decBtn.textContent = '-';

    const span = document.createElement('span');
    span.textContent = String(value);

    const incBtn = document.createElement('button');
    incBtn.textContent = '+';

    // Обработка клика на минус
    decBtn.addEventListener('click', () => {
      value -= 1;
      span.textContent = String(value);
      this._emitChange(value); // Уведомляем внешний код
    });

    // Обработка клика на плюс
    incBtn.addEventListener('click', () => {
      value += 1;
      span.textContent = String(value);
      this._emitChange(value);
    });

    wrapper.appendChild(decBtn);
    wrapper.appendChild(span);
    wrapper.appendChild(incBtn);

    shadow.appendChild(style);
    shadow.appendChild(wrapper);

    this._value = value;
    this._span = span;
  }

  _emitChange(value) {
    // Отправляем событие change с текущим значением
    this.dispatchEvent(
      new CustomEvent('change', {
        detail: { value },
        bubbles: true,  // Событие поднимается выше
        composed: true, // Проходит через Shadow DOM
      })
    );
  }

  get value() {
    return this._value;
  }

  set value(v) {
    const num = Number(v);
    if (!Number.isNaN(num)) {
      this._value = num;
      if (this._span) {
        this._span.textContent = String(num);
      }
      this._emitChange(num);
    }
  }
}

customElements.define('x-counter', CounterElement);

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

<x-counter value="5"></x-counter>

<script>
  const counter = document.querySelector('x-counter');

  // Подписываемся на событие change
  counter.addEventListener('change', (event) => {
    // Выводим новое значение счетчика
    console.log('Новое значение счетчика', event.detail.value);
  });

  // Программно меняем значение
  setTimeout(() => {
    counter.value = 10;
  }, 2000);
</script>

Здесь компонент инкапсулирует всю логику счётчика, а внешний код просто подписывается на одно событие и читает detail.


Архитектурные советы по проектированию кастомных элементов

Разделяйте внешний контракт и внутреннюю реализацию

Старайтесь чётко определить, что является "публичным" интерфейсом вашего компонента:

  • какие атрибуты он принимает;
  • какие свойства и методы доступны снаружи;
  • какие события он генерирует.

Дальше можно менять внутреннюю реализацию, не трогая этот контракт.

Например, для модального окна:

  • атрибуты: open (открыто/закрыто), title;
  • методы: open(), close(), toggle();
  • события: open, close.

Не завязывайтесь жёстко на внешний CSS

Если компонент без Shadow DOM, легко "сломать" его стилями со страницы. Если вам важна надёжная предсказуемость, используйте Shadow DOM и CSS‑переменные.

Делайте поведение явным

Если элемент генерирует события — задокументируйте их названия и структуру detail. Если элемент имеет методы — слегка прокомментируйте их назначение в коде.


Кроссбраузерность и поддержка

Поддерживаемые браузеры

На момент актуальных стандартов:

  • современные версии Chrome, Edge, Safari, Firefox поддерживают Custom Elements v1;
  • поддержка customized built-in elements (extends) в некоторых браузерах всё ещё ограничена;
  • для старых браузеров (например, старые мобильные или IE) нужен полифилл.

Полифиллы

Вы можете использовать официальные полифиллы от сообщества Web Components (например, пакет @webcomponents/custom-elements). Они позволяют запустить кастомные элементы в браузерах, где поддержки нет или она неполная.

Подключение обычно делается в <head> условно, если полифилл нужен.


Заключение

Кастомные элементы — это мощный способ создавать свои собственные HTML‑теги, которые:

  • инкапсулируют разметку, логику и стили;
  • могут быть повторно использованы в разных проектах;
  • хорошо сочетаются с Shadow DOM и CSS‑переменными;
  • работают без дополнительных фреймворков и зависят только от стандартов браузера.

Вы увидели, как:

  • зарегистрировать элемент с помощью customElements.define;
  • использовать колбэки жизненного цикла для инициализации и очистки;
  • связывать атрибуты и свойства;
  • передавать контент через слоты;
  • генерировать собственные события для внешнего кода.

На практике кастомные элементы позволяют постепенно "выносить" повторяющиеся куски интерфейса в отдельные, самодостаточные компоненты и использовать их как строительные блоки.


Частозадаваемые технические вопросы по теме и ответы

1. Как отложить регистрацию кастомного элемента до загрузки определённого модуля

Можно сначала динамически импортировать модуль, а затем вызывать customElements.define:

// Загружаем модуль только при необходимости
import('./components/user-card.js').then(({ UserCard }) => {
  // Регистрируем элемент после загрузки кода
  if (!customElements.get('user-card')) {
    customElements.define('user-card', UserCard);
  }
});

Здесь важно проверять, не был ли элемент уже зарегистрирован.


2. Как дождаться готовности элемента, если он регистрируется позже по времени

Используйте customElements.whenDefined:

customElements.whenDefined('user-card').then(() => {
  const card = document.querySelector('user-card');
  // Здесь уже можно безопасно вызывать методы компонента
  card.refresh && card.refresh();
});

Этот промис зарезолвится, как только элемент будет зарегистрирован.


3. Как типизировать кастомные элементы в TypeScript

Нужно расширить глобальный интерфейс HTMLElementTagNameMap:

declare global {
  interface HTMLElementTagNameMap {
    'user-card': UserCard; // Ваш класс
  }
}

После этого document.querySelector('user-card') будет иметь корректный тип UserCard | null.


4. Как правильно тестировать кастомные элементы

Обычно используют тестовый раннер (Jest, Vitest, Karma) в связке с JSDOM или реальным браузером:

  1. Импортируете модуль с customElements.define.
  2. Создаёте элемент через document.createElement('my-element').
  3. Добавляете его в document.body, чтобы сработал connectedCallback.
  4. Проверяете DOM, атрибуты и реакции на события.

Важно вызывать await Promise.resolve() или await new Promise(requestAnimationFrame) между шагами, если логика основана на микрозадачах.


5. Как передать сложный объект в кастомный элемент без сериализации в атрибут

Лучше использовать JavaScript‑свойства:

const user = { id: 1, name: 'Alice' };
const card = document.createElement('user-card');
card.user = user; // Внутри компонента реализуйте сеттер user
document.body.appendChild(card);

А внутри класса:

set user(value) {
  this._user = value;
  this._render();
}

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

Стрелочка влевоГлубокое изучение документации Vue и как эффективно её использоватьИспользование Crystal с Vue для разработкиСтрелочка вправо

Постройте личный план изучения Vue до уровня Middle — бесплатно!

Vue — часть карты развития Frontend

  • step100+ шагов развития
  • lessons30 бесплатных лекций
  • lessons300 бонусных рублей на счет

Бесплатные лекции

Все гайды по Vue

Руководство по валидации форм во Vue.jsИнтеграция Tiptap для создания редакторов на VueРабота с таблицами во Vue через TanStackИнструкция по установке и компонентам Vue sliderУправление пакетами Vue js с помощью npmУправление пакетами и node modules в Vue проектахКак использовать meta для улучшения SEO на VueПолный гайд по компоненту messages во Vuejs5 правил использования Inertia с Vue и LaravelРабота с модулями и пакетами в VueИнструкция по работе с grid на VueGithub для Vue проектов - подробная инструкция по хранению и совместной работеНастройка ESLint для Vue проектов и поддержка качества кодаОбработка ошибок и отладка в Vue.jsИспользование Vue Devtools для отладки и мониторинга приложенийРабота с конфигурационными файлами и скриптами VueСоздание и настройка проектов Vue с помощью Vue CLI3 способа интеграции Chart.js с Vue для создания графиковРабота с Canvas во VueИнструкция по реализации календаря во VueРабота с Ant Design Vue для создания UI на Vue
Vuex - полное руководство по управлению состоянием во Vue приложенияхРеактивные ссылки ref - полный разбор для разработчиковРеактивные объекты reactive-objects - подробное руководство с примерамиРеактивные переменные - концепция reactive и практические примерыМеханизм Provide Inject - как он работает и когда применятьPinia современный менеджер состояния для VueЛокальное состояние local state в веб разработкеГлобальное состояние в приложениях - global state
Обзор и использование утилит Vue для удобной разработкиРабота с обновлениями компонента и жизненным циклом updateРазрешение конфликтов и ошибок с помощью Vue resolveИспользование query-параметров и их обработка в маршрутах VueЗагрузка и управление состоянием загрузки в VueИспользование библиотек Vue для расширения функционалаРабота с JSON данными в приложениях VueКак работать с экземплярами компонента Instance во VueПолучение данных и API-запросы во Vue.jsЭкспорт и импорт данных и компонентов в VueОбработка событий и их передача между компонентами VuejsГайд по defineEmits на Vue 3Понимание core функционала Vue и его применениеПонимание и применение Composition API в Vue 3Понимание и работа с компилятором VueКогда и как использовать $emit и call во VueВзаимодействие с внешними API через Axios в Vue
Веб приложения на Vue архитектура и лучшие практикиРабота с URL и ссылками в приложениях на VueИспользование Vite для быстрого старта и сборки проектов на Vue 3Работа с пользовательскими интерфейсами и UI библиотеками во VueОрганизация и структура исходных файлов в проектах VueИспользование Quasar Framework для разработки на Vue с готовыми UI-компонентамиОбзор популярных шаблонов и стартовых проектов на VueИнтеграция Vue с PHP для создания динамичных веб-приложенийКак организовать страницы и маршруты в проекте на VueNuxt JS и Vue 3 для SSR приложенийСоздание серверных приложений на Vue с помощью Nuxt jsИспользование Vue Native для разработки мобильных приложенийОрганизация и управление индексной страницей в проектах VueИспользование Docker для контейнеризации приложений на VueИнтеграция Vue.js с Django для создания полноценных веб-приложенийСоздание и работа с дистрибутивом build dist Vue приложенийРабота со стилями и CSS в Vue js для красивых интерфейсовСоздание и структурирование Vue.js приложенияКак исправить ошибку cannot find module vueНастройка и сборка проектов Vue с использованием современных инструментовИнтеграция Vue с Bitrix для корпоративных решенийРазработка административных панелей на Vue js
Функция append в Go GolangОтображение компонента mounted - практическое руководствоХуки жизненного цикла компонентов - полное руководство для разработчиковУничтожение компонента destroyed - как правильно очищать ресурсы и подпискиИнициализация данных в состоянии created - как и когда подготавливать данные в приложенииОбновление компонента beforeUpdate во VueМонтирование компонента - хук beforeMount в VueРазрушение компонента во Vue - beforeDestroy и beforeUnmountСоздание экземпляра beforeCreate - полный разбор жизненного цикла
5 библиотек для создания tree view во VueИнтеграция Tailwind CSS с Vue для современных интерфейсовИнтеграция Vue с серверной частью и HTTPS настройкамиКак обрабатывать async операции с Promise во VueРуководство по интеграции Vue js в NET проектыИнтеграция Node.js и Vue.js для разработки приложенийПримеры использования JSX во VueГайд по импорту и регистрации компонентов на VueМногоязычные приложения на Vue с i18nИнтеграция FLIR данных с Vue5 примеров использования filter во Vue для упрощения разработки3 примера реализации drag-and-drop во Vue
Слоты компонента - концепция и практическое использованиеРегистрация компонентов component-registration в приложениях с внедрением зависимостейProps компонента в React - полный разбор с примерамиФункциональные компоненты в React - функциональный подход к построению интерфейсовСобытия компонента - events в современных интерфейсахДинамические компоненты - dynamic-componentsСоздание компонента component - практическое руководствоАсинхронные компоненты async-components - практическое руководство
Управление переменными и реактивными свойствами во VueНаблюдатели watchers - от паттерна до практических реализацийИспользование v for и slot в VueПрименение v-bind для динамической привязки атрибутов в VueУправление пользователями и их данными в Vue приложенияхСоздание и использование UI Kit для Vue приложенийТипизация и использование TypeScript в VuejsШаблоны Vue templates - практическое руководство для разработчиковИспользование шаблонов в Vue js для построения интерфейсовИспользование Swiper для создания слайдеров в VueРабота со стилями и стилизацией в VueСтруктура и особенности Single File Components SFC в VueРабота со SCSS в проектах на Vue для стилизацииРабота со скроллингом и прокруткой в Vue приложенияхПрименение script setup синтаксиса в Vue 3 для упрощения компонентовИспользование scoped стилей для изоляции CSS в компонентах Vue3 способа улучшить навигацию Vue с push()Обработка запросов и асинхронных операций в VueРеактивность Vue reactivity - как это работает под капотом и как этим пользоватьсяПонимание и использование provide inject для передачи данных между компонентамиПередача и использование props в Vue 3 для взаимодействия компонентовПередача данных между компонентами с помощью props в Vue jsУправление property и функциями во Vue.jsРабота со свойствами компонентов VueУправление параметрами и динамическими данными во VueОпции компонента в Go - паттерн component-optionsРабота с lifecycle-хуком onMounted во VueОсновы работы с объектами в VueПонимание жизненного цикла компонента Vue js на примере mountedИспользование модальных окон modal в Vue приложенияхИспользование методов в компонентах Vue для обработки логикиИспользование метода map в Vue для обработки массивовИспользование хуков жизненного цикла Vue для управления состоянием компонентаРабота с ключами key в списках и компонентах VueОбработка пользовательского ввода в Vue.jsРабота с изображениями и их оптимизация в VueИспользование хуков жизненного цикла в VueОрганизация сеток и гридов для верстки интерфейсов на VueСоздание и управление формами в VueОрганизация файлов и структура проекта Vue.jsКомпоненты Vue создание передача данных события и emitРабота с динамическими компонентами и данными в Vue3 способа манипулирования DOM на VueРуководство по div во VueИспользование директив в Vue и их расширенные возможностиОсновы и применение директив в VueИспользование директив и их особенности на Vue с помощью defineИспользование компонентов datepicker в Vue для выбора датОрганизация циклов и итераций во VueКак работает компиляция Vue CoreВычисляемые свойства computed во Vue.jsСоздание и использование компонентов в Vue JSОбработка кликов и пользовательских событий в VueИспользование классов в Vue для организации кода и компонентовИспользование директивы checked для управления состоянием чекбоксов в VueГайд на checkbox компонент во VueОтображение данных в виде графиков с помощью Vue ChartСоздание и настройка кнопок в VueСоздание и настройка кнопок в Vue приложенияхРабота с lifecycle-хуками beforeCreate и beforeMount во VueОсновы Vue - vue-basics для уверенного стартаИспользование массивов и методов их обработки в VueИспользование массивов и их обработка в Vue
Использование Vuetify для создания современных интерфейсов на VueИспользование transition во VueТестирование компонентов и приложений на VueТелепортация - архитектура и реализация в серверных приложенияхРабота с teleport для управления DOM во VueSuspense в React - управление асинхронными данными и ленивой загрузкойПять шагов по настройке SSR в VuejsИспользование Shadcn UI компонентов с Vue для продвинутых интерфейсовИспользование router-link для навигации в Vue RouterКак использовать require в Vue для динамического импорта модулейРабота с динамическим рендерингом и виртуальным DOM на Vue.jsИспользование ref для управления ссылками и реактивностью в Vue 3Использование Vue Pro и его преимущества для профессиональной разработкиПлагины Vue vue-plugins - полное практическое руководствоРуководство по nextTick для работы с DOMМиксины - mixins в современном программированииJSX в Vue с использованием плагина vue-jsxСоздание и использование компонентов с помощью Vue js и CУправление состоянием и реактивностью через inject и provideДинамическое обновление компонентов и данных на VueГлубокое изучение документации Vue и как эффективно её использоватьКастомные элементы - Custom Elements в современном JavaScriptИспользование Crystal с Vue для разработкиИспользование вычисляемых свойств для динамического отображения данных на Vue jsОптимизация производительности и предупреждения в Vue
Открыть базу знаний

Лучшие курсы по теме

изображение курса

Vue 3 и Pinia

Антон Ларичев
AI-тренажеры
Практика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.9
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

TypeScript с нуля

Антон Ларичев
AI-тренажеры
Практика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.8
3 999 ₽ 6 990 ₽
Подробнее
изображение курса

Next.js - с нуля

Антон Ларичев
AI-тренажеры
Практика в студии
Гарантия
Бонусы
иконка звёздочки рейтинга4.7
3 999 ₽ 6 990 ₽
Подробнее

Отправить комментарий