Vue.js обладает гибкой архитектурой, позволяющей работать с различными типами компонентов. Web Components — это стандартизированные, повторно используемые элементы пользовательского интерфейса, которые можно интегрировать в Vue-приложения без потери реактивности и удобства работы с шаблонами.
Для использования Web Components в Vue достаточно понять их отличие от стандартных Vue-компонентов:
customElements.define.Vue 3 корректно рендерит кастомные элементы, но чтобы избежать
конфликтов с синтаксисом Vue (v-model, v-on,
v-bind), необходимо учитывать особенности их работы.
Пример регистрации Web Component:
class MyButton extends HTMLElement {
constructor() {
super();
const shadow = this.attachShadow({ mode: 'open' });
shadow.innerHTML = `<button><slot></slot></button>`;
}
}
customElements.define('my-button', MyButton);
Использование в Vue:
<template>
<my-button @click="handleClick">Нажми меня</my-button>
</template>
<script>
export default {
methods: {
handleClick() {
console.log('Кнопка нажата');
}
}
}
</script>
Ключевой момент: Vue автоматически не привязывает
реактивность к атрибутам Web Component. Для работы с данными через
props нужно использовать специальные решения, например
v-bind с ref или обработку событий
вручную.
Для передачи данных используются атрибуты и события. Атрибуты работают только с примитивными значениями (строки, числа, булевы), а объекты требуют сериализации через JSON.
Пример передачи атрибута:
<template>
<my-button label="Отправить"></my-button>
</template>
Если требуется передать объект:
<template>
<my-button :data="JSON.stringify(userData)"></my-button>
</template>
<script>
export default {
data() {
return {
userData: { name: 'Алексей', age: 30 }
}
}
}
</script>
События Web Components слушаются стандартным
способом через addEventListener или через директиву Vue
v-on:
<my-button @custom-event="onCustomEvent"></my-button>
methods: {
onCustomEvent(event) {
console.log('Получено событие:', event.detail);
}
}
Web Components не обладают реактивностью Vue по умолчанию. Для интеграции реактивных данных:
ref для доступа к DOM-элементу Web
Component.Пример:
<template>
<my-counter ref="counter"></my-counter>
<button @click="increment">Увеличить</button>
</template>
<script>
export default {
methods: {
increment() {
this.$refs.counter.value += 1;
}
}
}
</script>
Web Components поддерживают слоты, которые позволяют вставлять контент внутрь компонента. В Vue это работает нативно через стандартный синтаксис:
<my-card>
<h3 slot="header">Заголовок карты</h3>
<p>Содержимое карты</p>
</my-card>
Для сложной интеграции со Vue-слотами может потребоваться ручное
управление содержимым через innerHTML или
template внутри Shadow DOM.
input или change.mounted,
updated) применяются к обертке, а не к Shadow DOM Web
Component.window.Для сторонних библиотек, предоставляющих кастомные элементы
(например, Vaadin, Shoelace), Vue поддерживает
их как обычные HTML-теги. Важно:
customElements.define.v-bind и v-on для
синхронизации с реактивными данными.Пример интеграции Shoelace Button:
<template>
<sl-button type="primary" @sl-click="submitForm">Отправить</sl-button>
</template>
<script>
export default {
methods: {
submitForm() {
console.log('Форма отправлена');
}
}
}
</script>
Интеграция Web Components в Vue.js позволяет сочетать стандартизированные элементы интерфейса с мощной реактивностью и гибкостью Vue, обеспечивая масштабируемость и повторное использование компонентов без потери производительности.