Custom Elements (пользовательские элементы) представляют собой стандартизированный способ создания повторно используемых HTML-компонентов, которые могут работать вне зависимости от фреймворка. Vue.js начиная с версии 3 поддерживает интеграцию с Custom Elements через механизм Vue Custom Element Wrapper, позволяя экспортировать компоненты Vue как нативные веб-компоненты.
Ключевой момент: при использовании Custom Elements Vue-компонент становится самодостаточным элементом, который можно вставлять в любой HTML-документ, включая проекты на других фреймворках.
Для создания пользовательского элемента необходимо подготовить
обычный Vue-компонент и обернуть его с помощью функции
defineCustomElement:
import { defineCustomElement } from 'vue';
import MyComponent from './MyComponent.vue';
const MyCustomElement = defineCustomElement(MyComponent);
customElements.define('my-custom-element', MyCustomElement);
Объяснение кода:
defineCustomElement принимает обычный компонент Vue и
возвращает конструктор, совместимый с браузерным API
customElements.customElements.define регистрирует элемент с уникальным
именем, которое должно содержать дефис (-) по стандарту
HTML.После этого
<my-custom-element></my-custom-element> можно
использовать в любом HTML-документе.
Custom Elements поддерживают передачу данных через атрибуты HTML. Vue автоматически синхронизирует атрибуты с пропсами компонента:
<template>
<p>{{ message }}</p>
</template>
<script>
export default {
props: {
message: {
type: String,
default: 'Привет, мир!'
}
}
}
</script>
Использование в HTML:
<my-custom-element message="Hello from HTML"></my-custom-element>
Vue преобразует атрибут message в пропс
message внутри компонента. Важно: для передачи сложных
объектов или массивов потребуется сериализация в JSON и десериализация
внутри компонента.
Vue-компоненты в виде Custom Elements могут генерировать стандартные события DOM, что позволяет взаимодействовать с ними вне Vue-контекста:
// В компоненте
export default {
methods: {
emitEvent() {
this.$emit('custom-event', { data: 123 });
}
}
}
HTML-обработчик:
<my-custom-element id="example"></my-custom-element>
<script>
const el = document.getElementById('example');
el.addEventListener('custom-event', event => {
console.log(event.detail); // { data: 123 }
});
</script>
Особенности:
this.$emit генерирует событие с использованием
CustomEvent, доступное в обычном DOM.Custom Elements поддерживают стандартные коллбэки жизненного цикла:
connectedCallback – вызывается при вставке элемента в
DOM.disconnectedCallback – вызывается при удалении элемента
из DOM.attributeChangedCallback – реагирует на изменения
атрибутов.Vue автоматически связывает эти коллбэки с жизненным циклом компонента, что обеспечивает корректную инициализацию и уничтожение:
mounted компонента Vue соответствует
connectedCallback.unmounted – соответствует
disconnectedCallback.Custom Elements могут использовать Shadow DOM, что
гарантирует изоляцию стилей. В Vue это достигается настройкой
shadow: true при создании кастомного элемента:
const MyCustomElement = defineCustomElement(MyComponent, { shadow: true });
customElements.define('my-shadow-element', MyCustomElement);
Преимущества Shadow DOM:
Vue позволяет загружать Custom Elements лениво, что полезно для оптимизации крупных проектов:
import { defineAsyncCustomElement } from 'vue';
const LazyElement = defineAsyncCustomElement(() =>
import('./HeavyComponent.vue')
);
customElements.define('lazy-element', LazyElement);
Custom Elements, созданные на Vue, полностью совместимы с React, Angular, Svelte или чистым Jav * aScript:
<my-custom-element message="Привет"></my-custom-element>
<script>
document.querySelector('my-custom-element')
.addEventListener('custom-event', e => console.log(e.detail));
</script>
Это делает Vue Custom Elements удобным инструментом для микрофронтенд-архитектуры, где разные части приложения могут использовать разные технологии.