Zpět na domů

Symbiote.js: kompozice webových komponent bez virtuálního DOM | Průvodce

Technický průvodce použitím Symbiote.js pro vytváření webových komponent. Rozkládáme implementaci záložek, mechanismy shared context a výhody low-code přístupu. Vhodné pro middle/senior vývojáře.

Symbiote.js: jak skládat rozhraní jako konstruktor prostřednictvím HTML
Advertisement 728x90

Symbiote.js: pokročilá kompozice webových komponent bez virtuálního DOM

Symbiote.js — lehká (~6 kB Brotli) knihovna pro tvorbu webových komponent, zaměřená na pokročilou kompozici prostřednictvím HTML rozbalení. Řeší problém strukturální organizace rozhraní, eliminuje závislost na virtuálním DOM a poskytuje flexibilní mechanismy pro práci s datovými kontexty. Na rozdíl od tradičních frameworků Symbiote.js pracuje přímo s DOM API, minimalizuje boilerplate a umožňuje kombinovat komponenty deklarativní rozbalkou.

Základy strukturální kompozice

Vývoj rozhraní se skládá ze dvou aspektů: logické modelu (komponenty, data) a strukturální kompozice (vazby mezi komponentami, tok dat). Symbiote.js nabízí unikátní přístup k druhému, používá HTML jako prvotřídní nástroj pro definici závislostí. Klíčové principy:

  • Šablony komponent — nezávislé HTML řetězce
  • Vnější rozbalení definuje strukturální vazby
  • Žádná vazba na JS runtime
  • Podpora hybridních přístupů (render na serveru/klientu)

To umožňuje oživit předem generovanou rozbalku, vytvářet „hloupé“ komponenty bez vlastní logiky nebo používat poskytovatele kontextu. Příklad — implementace tabů prostřednictvím dvou propojených komponent:

Google AdInline article slot
import Symbiote, { css } from '@symbiotejs/symbiote';

class SuperTabs extends Symbiote {
  init$ = {
    '*currentTabName': 'first',
  };

  renderCallback() {
    this.tabEls = [...this.querySelectorAll('[tab]')];
    this.tabEls.forEach((/** @type {HTMLElement} */ el) => {
      let tab = el.getAttribute('tab');
      if (el.hasAttribute('current')) {
        this.$['*currentTabName'] = tab;
      }
      el.onclick = () => {
        this.$['*currentTabName'] = tab;
      };
    });
    this.sub('*currentTabName', (val) => {
      this.tabEls.forEach((/** @type {HTMLElement} */ el) => {
        if (el.getAttribute('tab') === val) {
          el.setAttribute('current', '');
        } else {
          el.removeAttribute('current');
        }
      });
    });
  }
}

SuperTabs.rootStyles = css`
super-tabs {
  display: inline-flex;
  gap: 2px;
  [tab] {
    cursor: pointer;
    &[current] {
      background-color: transparent;
      pointer-events: none;
    }
  }
}
`;

SuperTabs.reg('super-tabs');

Druhá komponenta zpracovává zobrazení obsahu:

class SuperTabsView extends Symbiote {
  renderCallback() {
    this.tabCtxEls = [...this.querySelectorAll('[tab-ctx]')];
    this.sub('*currentTabName', (val) => {
      this.tabCtxEls.forEach((/** @type {HTMLElement} */ el) => {
        if (el.getAttribute('tab-ctx') === val) {
          el.setAttribute('active', '');
        } else {
          el.removeAttribute('active');
        }
      });
    });
  }
}

SuperTabsView.rootStyles = css`
super-tabs-view {
  display: block;
  [tab-ctx] {
    display: none;
    &[active] {
      display: contents;
    }
  }
}
`;

SuperTabsView.reg('super-tabs-view');

Klíčové technické vlastnosti

Příklad demonstruje pět klíčových mechanismů:

  • rootStyles — styly se aplikují správně bez ohledu na přítomnost Shadow DOM v rodičovských prvcích. To zaručuje kompatibilitu s Tailwind, Bootstrap a globálními styly.
  • renderCallback — životní cyklus s přístupem k dceřiným uzlům (na rozdíl od standardního connectedCallback).
  • init$ — inicializace reaktivních vlastností s výchozími hodnotami.
  • sub() — odběr změn vlastností přes Pub/Sub bez virtuálního DOM.
  • *Vlastnosti přes (hvězdička)** — deklarace sdíleného kontextu (analogicky atributu name u input[type=radio]).

Vlastností architektury je přímá práce s DOM API bez abstrakcí. To není antipattern, ale vědomá volba, která eliminuje režii virtuální reprezentace. Přitom knihovna podporuje typizaci, reaktivitu a runtime ladění.

Google AdInline article slot

Low-code paradigma v akci

Výhoda Symbiote.js se projevuje ve scénářích, kde se rozhraní skládají prostřednictvím HTML atributů bez JavaScriptu. Podívejme se na komponentu pro zobrazení aktuálního tabu:

class SuperCurrent extends Symbiote {}

SuperCurrent.rootStyles = css`
super-current {
  display: block;
  h2 {
    text-transform: capitalize;
  }
}
`;

SuperCurrent.template = html`<h2>{{*currentTabName}}</h2>`;

SuperCurrent.reg('super-current');

Použití:

<super-current ctx="section-select"></super-current>

Takový přístup otevírá možnosti pro:

Google AdInline article slot
  • Designéry: prototypování rozhraní přímo v HTML
  • Content managery: nastavení zobrazení atributy bez kódu
  • Vkládaná řešení: konfigurace widgetů rozbalkou
  • AI systémy: generování rozhraní s předvídatelnou vazbou rozbaly a chování

Čím více komponent v knihovně, tím jednodušší je skládat složitá rozhraní přes HTML. Každá skupina komponent je izolována atributem ctx, což umožňuje umístit na stránku více nezávislých instancí.

Co je důležité

  • Nulová závislost na builderech: komponenty fungují bez Webpack/Vite
  • Kontext přes DOM: vazby mezi komponentami definuje struktura rozbaly
  • 6 kB velikost: minimální dopad na výkon
  • Kompatibilita s jakýmkoli stackem: integrace do existujících projektů bez migrace
  • Typy „z krabice“: podpora TypeScript bez dalšího nastavení

Symbiote.js nenahrazuje frameworky, ale je doplňuje v oblastech strukturální kompozice. Pro logické úlohy poskytuje minimalistický API, zaměřený na to, co jiné řešení implementují přes externí knihovny (state management, routing). To snižuje kognitivní zátěž při návrhu rozhraní, zejména v týmech s různorodým složením.

— Editorial Team

Advertisement 728x90

Číst dál