Быстрый старт с WebComponents

Nikita
WebbDEV
Published in
5 min readJul 31, 2019

--

Веб-компоненты это набор стандартов определяющих программные интерфейсы для организации компонентной архитектуры. Все они реализованы в современных версиях браузеров, т.е. не требуют подключения библиотек или транспиляторов кода, однако, если нужна совместимость например с Internet Explorer 11, то и библиотеки и транспиляторы использовать видимо все-таки придется.

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

Все эксперименты приводимые далее проверялись в Chrome и Firefox может быть даже не самых новых версий.

Итак начнем.

Для начала создадим директорию для проекта и перейдем в него.

Выполним:

В этом каталоге ответив на все вопросы по умолчанию.

Создадим в каталоге файл index.html с самым простым содержимым.

Добавим тег для элемента, имя должно обязательно содержать дефис, это сигнал для подсистемы CusomElements для попытки определения этого элемента как надстраивающего стандартные.

Добавим класс обработчик в теге script.

В модульном теге script, мы определили новый класс который c помощью метода customElements.define() определили за тегом my-webcomp. А добавив код в метод connectedCallback() мы обеспечили его вызов при добавлении реализации компонента в дерево. Результат уже можно посмотреть в браузере:

Результат

Однако, размещать html верстку прямо в код если и удобно для небольших кусочков, то вообще не правильно, что особенно сказывается когда кусочки разрастаются до приличных размеров. Например на форме с 20ю элементами, которую побить на подкомпоненты тоже не всегда может быть удобно. Поэтому мы для начала вынесем верстку в шаблон, который будет располагаться в том же html, хотя ничто не помешает его нам загрузить из отдельного файла при необходимости.

В коде компонента вставку строки c html мы заменили на получение элемента шаблона по id. Импорт, т.е. создание копии этого элемента и присоединение к содержимому текущего.

id назван в нотации camelCase т.к. все айдишники элементов прокидываются в глобальное пространство имен и при использовании дефисов или других спец. символов доступ к ним может быть менее элегантен. Т.е. мы могли бы вместо:

написать в одну строчку:

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

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

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

Теперь при нажатии на сообщение у нас будет реакция на действия пользователя.

Аргументом метода showMessage() также объявляется объект event, который хранит данные о событии, например координаты клика или ссылку на сам элемент.

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

Добавим второй экземпляр элемента и определим для каждого из них разные свойства greet-name значения которых будут выводиться при нажатии на элемент.

Теперь при нажатии на первый будет выводиться “This is the message for John”, а на второй “This is the message for Josh”.

Может так случиться что атрибут надо будет использовать не в обработке события, а прямо рендерить в шаблон, для этого мы добавим id целевому элементу и подставим значение из API сразу после рендеринга копии объекта шаблона.

Получается вот так:

Вместо .textContent может быть .innerHTML или можно вызвать у объекта из селектора тот же метод .insertAdjacentHTML() мы делали в самом начале.

Долгое время использование id считалось дурным тоном, потому что на значительных объемах кода они могли дублироваться, что приводило к коллизиям. Однако, с появлением технологии теневого дерева можно внутреннее содержимое элемента изолировать использовать id, стили и прочие ресурсы без опасений. Для веб-компонентов включается теневое дерево следующим образом:

Теперь правда все DOM обращения к this придется заменить на this.shadowRoot благо их пока не так много.

Визуально работа этого кода опять никак не изменится, но теперь в глобальном пространстве имен не будет никакого helloLabel, а у на странице уже 2 элемента с таким идентификатором. А получить доступ к ним можно будет например вот так:

И то если вы не закроете дерево передав соответствующий атрибут в методе .attachShadow().

У нас получилось довольно много кода и размещать его прямо в html файле тоже не очень правильно. Поэтому создадим файл my-webcomp.js и перенесем в него наш класс предварив инструкцией export, а в теге script добавим импорт этого класса, чтобы получилось вот такое:

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

Правда с этого момента открывать index.html как локальный для разработки не получится, т.к. браузер заблокирует загрузку скрипта с файловой системы. Если у вас есть nodejs можно поставить простейший веб-сервер:

И запускать его командой http-server в каталоге с проектом, при запуске он подскажет хост и порт с которого можно открывать страницу http://127.0.0.1:8080

Которая и будет отныне адресом отладочной страницы с нашим элементом.

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

Книг на тему пока не так уж много, но вся расширенная документация легко находится по словам Web Components, CustomElements, ShadowDOM, Native Template Tag, Custom Events.

--

--