В этом посте я опишу, как настроить современную маршрутизацию и использовать сигналы для реактивного отключения выбранных ссылок.
Сигналы — это просто реализация паттерна "observable". Хотя мы могли бы использовать любую библиотеку для этой цели, мы создадим свою собственную, чтобы обеспечить лучшую наглядность и понимание.
export class Observable { #callbacks = new Set(); notify() { for (const fn of this.#callbacks) fn(); } subscribe(callback) { this.#callbacks.add(callback); return () => this.#callbacks.delete(callback); // unsubscribe } }
Далее нам нужно будет создать библиотеку маршрутизации для нашего приложения. Реализация маршрутизации в современных браузерах проста и не требует использования сторонних библиотек.
import { update } from "@fusorjs/dom"; import { Observable } from "./observable"; const observable = new Observable(); let route = location.hash; window.addEventListener( "popstate", () => { route = location.hash; observable.notify(); }, false ); export const getRoute = () => route; export const mountRoute = (self) => observable.subscribe(() => update(self));
Далее нам нужен реактивный компонент ссылки, который изменяет свой DOM-узел с элемента a на обычный текст, если текущий маршрут совпадает с его собственным маршрутом.
import { span, a } from "@fusorjs/dom/html"; import { mountRoute, getRoute } from "./route"; const RouteLink = (title, route) => span( { mount: mountRoute }, // enable reactivity ((cache = a({ href: route }, title)) => () => getRoute() === route ? title : cache)() );
Обратите внимание, что в Fusor существует три способа определить HTML-элемент. В приведённом выше примере используются функции span и a. Второй способ включает использование JSX.
<span mount={mountRoute}>{( (cache = <a href={route}>{title}</a>) => () => getRoute() === route ? title : cache )()}</span>
И третий использует функцию h("span", {mount: mountRoute}, .....
Свойство mount позволяет назначить функцию, которая срабатывает, когда элемент присоединяется к DOM. Обратитесь к разделу "Жизненный цикл компонентов" в туториале для получения более подробной информации.
Наконец, мы используем наш компонент для динамического создания списка ссылок и их прикрепления к DOM.
import { getElement } from "@fusorjs/dom"; import { ul, li } from "@fusorjs/dom/html"; import { RouteLink } from "./route-link"; const block = ul( [...Array(10)].map((_, i) => li(RouteLink(`${i}. Section`, `#url-to-${i}-section`)) ) ); document.body.append(getElement(block));
Посмотрите пожалуйста полный рабочий пример.
Репозиторий Fusor.
Спасибо!
