Использование веб-компонентов JavaScript

Веб-компоненты позволяют нам создавать многократно используемые пользовательские HTML-элементы, функциональность которых изолирована от остального кода. Это можно комбинировать с модулями ES для создания компонентной архитектуры для веб-сайтов с использованием HTML, CSS и ванильного JavaScript.

Следуя этому подходу, можно написать одностраничное приложение без использования каких-либо фреймворков или библиотек JavaScript. Эта статья поможет вам понять, как этого можно достичь.

Полный код доступен на GitHub.

Попробуйте эту архитектуру на StackBlitz.

Архитектура

Базовая папка приложения состоит из index.html, script.js и style.css. Эти три файла в основном содержат шаблонный код, который может оставаться одинаковым для любого приложения, созданного с использованием этой архитектуры. Базовая папка также содержит папку 'src', в которой находится весь исходный код приложения. Эта папка содержит AppModule, AppComponentбазовый компонент, все дочерние компоненты и службы. AppModule и AppComponent являются обязательными файлами, которые образуют точку входа в настройку. Эти файлы также содержат некоторый шаблонный код.

Изучение базовой папки

Три файла в базовой папке (index.html, script.js, style.css) образуют отправную точку для приложения.

Index.html

Это шаблонный HTML-файл, в котором в разделе <head> определен файл script.js и связан файл style.css. Файл script.js указывается с type='module' для включения модулей ES. Он также помечен 'defer', чтобы загрузить его после загрузки HTML.

Тело index.html не содержит ничего, кроме ссылки на <app-root>. Этот файл является единственным файлом HTML во всем приложении.

script.js

Файл script.js содержит определение AppModule, которое формирует точку входа для остальной части приложения.

Файл style.css содержит общие стили для приложения, а также связан с файлом index.html.

Изучение папки src'

Основная часть приложения находится в папке src.

Модуль

Он начинается с appModule.js, который является единственным файлом, на который есть ссылка вне папки «src». Он импортируется в файл script.js, как показано выше. appModule.js содержит экспортированный класс с именем 'AppModule', который содержит определение метода defineElements(). Этот метод вызывается из файла script.js. Все компоненты, присутствующие в приложении, включая базовый компонент и все дочерние компоненты, определяются в теле этого метода.

В приведенном ниже примере мы видим, что AppComponent определяется как app-root, а childOneComponent определяется как child-one.

Компоненты

Каждый компонент в этой архитектуре состоит из двух частей. Первый — это файл JavaScript, который определяет шаблон HTML и методы компонента. Второй файл CSS, который определяет стили для компонента и импортируется в шаблон.

Файл JavaScript компонента состоит из определения HTML template и определения класса компонента. Класс компонента является расширением базового класса HTMLElement. Этот класс определяет конструктор и два метода жизненного цикла компонента. Метод жизненного цикла connectedCallback() запускается, как только компонент подключается (загружается) к DOM, а disconnectedCallback() запускается, как только компонент отключается (удаляется) от DOM.

Базовый компонент

appComponent.js — это веб-компонент JavaScript, который формирует базовый компонент приложения. Это можно рассматривать как обязательную часть архитектуры, поскольку это единственный компонент, доступный извне для файла index.html как <app-root>.

В приведенном выше примере шаблон appComponent содержит тег <style>, который импортирует appComponent.css, и тег <div>, формирующий тело компонента. В теле компонента есть тег <h1> с заголовком 'App Component' и тег <child-one>.

Класс AppComponent содержит базовый шаблонный код веб-компонента, необходимый для нормальной работы приложения.

Дочерние компоненты

Дочерние компоненты помещаются в папку components. Все создаваемые дочерние компоненты должны быть определены в AppModule и напрямую или косвенно связаны с appComponent.

В приведенном выше примере шаблон childOneComponent содержит тег <style>, который импортирует childOneComponent.css, и тег <div>, формирующий тело компонента. В теле есть тег <h2> с заголовком 'Child One'.

Это приложение при запуске формирует указанную выше структуру DOM. <app-root> содержит тело AppComponent в Shadow Root. Точно так же тело компонента <child-one> содержится во вложенном теневом корне.

Услуги

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

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

Приведенный выше пример SampleDataService содержит статический массив state и два других статических метода для управления state. Метод addItem() помещает элемент в state, а метод getItem() получает элемент из state с помощью id. Эти методы могут быть вызваны из любой точки приложения.

import { SampleDataService } from "./services/SampleDataService.js";

SampleDataService импортируется в соответствующий файл, где он будет использоваться. Если мы хотим добавить элемент или два в состояние после загрузки AppComponent, мы вызываем SampleDataService.addItem() из connectedCallback из AppComponent.

connectedCallback() {
    SampleDataService.addItem({ id: 1, value: “Item 1” });
    SampleDataService.addItem({ id: 2, value: “Item 2” });
}

Если мы хотим вывести определенный элемент на консоль после загрузки ChildOneComponent, мы вызываем SampleDataService.getItem(id), передавая ему идентификатор элемента из connectedCallback из ChildOneComponent. Затем мы можем вывести значение на консоль, используя console.log().

connectedCallback() {
   let item = SampleDataService.getItem(1);
   console.log("Child One: ", item);
}

Описанный выше подход к управлению состоянием небезопасен из-за изменяемой переменной состояния. Состояние может быть изолировано от служб с помощью шаблона Redux для повышения безопасности.

Заключение

В завершение мы рассмотрели, как создать одностраничное приложение с использованием веб-компонентов и модулей JavaScript ES. Мы изучили архитектуру и структуру папок, созданные для этого подхода. Мы также изучили все файлы, которые требуются в качестве шаблона для приложения, и увидели, как его можно настроить.

Код для этой архитектуры доступен на GitHub.

Вы можете опробовать эту архитектуру на StackBlitz.

Дополнительные материалы на PlainEnglish.io. Подпишитесь на нашу бесплатную еженедельную рассылку новостей. Подпишитесь на нас в Twitter и LinkedIn. Присоединяйтесь к нашему сообществу Discord.