Перейти к содержимому

32. Web Components Best Practices

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

Web Components - это набор веб-стандартов, позволяющих создавать пользовательские HTML-элементы с собственной логикой и стилями. Они полезны для повторного использования кода, инкапсуляции функциональности и создания более структурированных веб-приложений. Представьте, что вы можете создать свой собственный <my-button>, который будет работать везде!

  1. Используйте Shadow DOM для инкапсуляции: Shadow DOM изолирует стили и скрипты компонента, предотвращая их конфликт с остальной частью страницы.

    class MyButton extends HTMLElement {
    constructor() {
    super();
    this.attachShadow({ mode: 'open' }); // Создаем Shadow DOM
    this.shadowRoot.innerHTML = `
    <style>
    button {
    background-color: blue;
    color: white;
    padding: 10px 20px;
    border: none;
    cursor: pointer;
    }
    </style>
    <button>Click Me!</button>
    `;
    }
    }
    customElements.define('my-button', MyButton);

    В этом примере стили внутри <style> применяются только к кнопке внутри Shadow DOM, не влияя на другие кнопки на странице.

  2. Определяйте API компонента через атрибуты и свойства: Атрибуты HTML и свойства JavaScript служат для взаимодействия с компонентом извне.

    class MyGreeting extends HTMLElement {
    static get observedAttributes() {
    return ['name']; // Отслеживаем изменения атрибута 'name'
    }
    constructor() {
    super();
    this.attachShadow({ mode: 'open' });
    this.shadowRoot.innerHTML = `
    <p>Hello, <span id="name"></span>!</p>
    `;
    }
    attributeChangedCallback(name, oldValue, newValue) {
    if (name === 'name') {
    this.shadowRoot.querySelector('#name').textContent = newValue;
    }
    }
    }
    customElements.define('my-greeting', MyGreeting);
    <my-greeting name="World"></my-greeting>

    Здесь атрибут name используется для передачи имени, которое отображается внутри компонента.

  3. Используйте Custom Events для коммуникации: Web Components могут отправлять пользовательские события, чтобы сообщать об изменениях или взаимодействиях.

    class MyCounter extends HTMLElement {
    constructor() {
    super();
    this.attachShadow({ mode: 'open' });
    this.shadowRoot.innerHTML = `
    <button id="increment">Increment</button>
    <span>Count: <span id="count">0</span></span>
    `;
    this.count = 0;
    this.shadowRoot.getElementById('increment').addEventListener('click', () => {
    this.count++;
    this.shadowRoot.querySelector('#count').textContent = this.count;
    this.dispatchEvent(new CustomEvent('count-changed', { detail: this.count })); // Отправляем событие
    });
    }
    }
    customElements.define('my-counter', MyCounter);
    const counter = document.querySelector('my-counter');
    counter.addEventListener('count-changed', (event) => {
    console.log('Count changed:', event.detail);
    });

    Компонент my-counter отправляет событие count-changed при каждом увеличении счетчика.

Многие современные фреймворки и библиотеки, такие как Angular, React (через библиотеки, такие как react-shadow-dom), и Vue (с использованием defineCustomElement), используют концепции, лежащие в основе Web Components. Кроме того, крупные компании, такие как Google (в проектах вроде Polymer и Material Web Components) и Adobe (в Adobe Creative Cloud), активно используют Web Components для создания переиспользуемых UI-элементов. Например, Material Web Components предоставляет готовый набор компонентов, соответствующих Material Design, которые можно использовать в любом проекте, независимо от используемого фреймворка.

  • Инкапсуляция стилей и скриптов с помощью Shadow DOM.
  • Определение API компонента через атрибуты и свойства.
  • Использование Custom Events для коммуникации между компонентами и остальной частью страницы.
  • Web Components - это стандарт, который можно использовать с любым фреймворком или без него.
  • Использование префиксов для имен компонентов (например, my-button) помогает избежать конфликтов имен.