Иногда кажется, что веб компоненты не дотягивают до фреймворка, особенно если сравнивать их с наиболее популярными представителями. Но многое самое насущное, что не закрывается реализацией стандартов входящих в понятие веб компонентов, достаточно легко прикрутить с помощью библиотек или небольшого объема своего изящного кода. Одной из таких возможностей является роутинг на стороне фронтенда. Фича не всегда необходимая, возможно даже спорная, но в большинстве фреймворков она присутствует и многими используется. Что же в веб-компонентах? А мы попробуем реализовать роутинг с помощью библиотеки navigo.

Чтобы консольные команды работали лучше в ОС Windows можно установить Unix-утилиты из дистрибутива гит под эту систему, ну или видимо использовать новые возможности WSL и терминалов.

Для начала создадим проект:

mkdir testnavigo
cd testnavigo
npm init

и много раз нажимаем энтер пока не отпустит

затем поставим библиотеку

npm i navigo --save

создадим index.html

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

Веб-компоненты подарили нам возможность автовызова хука при появлении элемента в дереве, за которым закреплен наш класс, в дереве объектов браузера. В нем мы и инициализируем библиотеку роутинга кодом прямо из примера с гитхаба библиотеки (в реально жизни это стоит сделать красивее с модульной загрузкой).

<script src="/node_modules/navigo/lib/navigo.min.js"></script>

<my-app></my-app>

<script type="module">

   class MyApp extends HTMLElement {

       connectedCallback() {
           let root = null;
           let useHash = true; // Defaults to: false
           let hash = '#!'; // Defaults to: '#'
           this.router = new Navigo(root, useHash, hash);
       }
    }
   customElements.define('my-app', MyApp);
</script>


Добавим обработку роутов:

connectedCallback() {
   let root = null;
   let useHash = true; // Defaults to: false
   let hash = '#!'; // Defaults to: '#'
   this.router = new Navigo(root, useHash, hash);
   router
       .on('page-a', () => {
           this.innerHTML = '';
           this.insertAdjacentHTML('beforeend', '<page-a></page-a>');
       })
       .on('page-b', () => {
           this.innerHTML = '';
           this.insertAdjacentHTML('beforeend', '<page-b></page-b>');
       })
       .on('*', () => {
           this.innerHTML = '';
           this.insertAdjacentHTML('beforeend', '<div>Please click links above</div>');
       })
       .resolve();
}


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

class PageA extends HTMLElement {
   connectedCallback() {
       this.insertAdjacentHTML('beforeend', '<div>This is a page A</div>');
   }
}
class PageB extends HTMLElement {
   connectedCallback() {
       this.insertAdjacentHTML('beforeend', '<div>This is a page B</div>');
   }
}
customElements.define('page-a', PageA);
customElements.define('page-b', PageB);


В самом верху страницы добавим ссылки, чтобы проверить навигацию:

<a href="page-a" data-navigo>Page A</a>
<a href="page-b" data-navigo>Page B</a>


атрибут data-navigo позволяет нажатия по ним обрабатывать роутером, а не осуществлять запросы на бекенд. Который пора уже запустить, например вот так:

npx http-server


открыть в браузере 127.0.0.1:8080 или какой он вам там напишет и убедиться, что все работает.



Теперь мы можем разнести все как полагается по отдельным файлам, приделать шаблонизацию и динамическую загрузку страниц, вынести роуты в концигурацию. Веб-компоненты возьмут на себя основную работу с Жизненным Циклом объектов приложения, только эвенты надо не забывать разбиндивать в хуке disconnectedCallback()

Поскольку я хотел показать насколько быстро это все делается, растягивать дальше статью пожалуй не буду;)

Об чем-то из этого я уже писал в статьях:

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

и

WebComponents как фреймворки, взаимодействие компонентов

Ждите новых открове^Wстатей, шэрьте и лайкайте!

Получившийся исходный код можно посмотреть вот репозитории на битбакете:

https://bitbucket.org/techminded/testnavigo/