[DajSięPoznać#8] Web Components i Aurelia

Wstęp

Jednym z ciekawszych standardów budowanych wokół HTML5 jest Web Components, dlatego tym razem trochę więcej na ten temat. Na głównej stronie Aurelii producenci na pierwszym miejscu stawiają “Forward-thinking”, a więc ES6, a także integrację z Web Components właśnie.

Problemy przy budowie aplikacji webowych

Pomimo ogromnego skoku, jaki zaliczyły technologie webowe w ostatnich latach, kilka problemów jest wciąż nierozwiązanych. Pierwszym z nich jest niedeskryptywny markup, tzn. widoki HTML ciężko się czyta, gdy są złożone w większości z div-ów, które nie mają wartości semantycznej. HTML5 wprowadził sporo nowych tagów, ale dobrze byłoby móc tworzyć własne i umieszczać je w widokach i tu właśnie z pomocą przychodzą Web Components. Kolejny problem jest taki, że wstawienie kontrolki wymaga dodania trzech referencji (html, js, css), co również nie jest zbyt wygodne. W ostatnim czasie twórcy frameworków nierzadko szli własnymi ścieżkami, np. angular problem niedeskryptywnego markupu zaadresował poprzez dyrektywy. Tu z pomocą przychodzą Web Components jako standard niezależny od jakiegokolwiek frameworka.

wc

Web Components

Standard budowany jest wokół 4 ważnych konceptów:

  • template, jako nowy tag htmla opisujący inercyjny fragment drzewa DOM, a więc taki, który wyrenderuje się dopiero po sklonowaniu i umieszczeniu w DOM hosta
  • custom-elements, a więc możlwość definiowania własnych tagów HTML
  • import, jako sposób na załączanie szablonów do strony
  • shadow DOM – koncepcja polegająca na wydzieleniu niezależnego fragmentu drzewa DOM strony (nazywanego light DOM) i odseparowaniu go od całej strony (ukrywając go przed kodem tradycyjnymi selektorami). Przykładem jest tag video z HTML5. Shadow DOM ignoruje tradycyjne, globalne style strony (choć można go stylować z zewnątrz operatorem /deep/).

Mamy zatem możliwość logicznej separacji elementów strony, co z reguły powinno znacznie ułatwić development.

Web Components w Aurelii

Aurelia z jednej strony używa tagu template przy definiowaniu komponentów, z drugiej pozwala na importowanie zewnętrznych komponentów i bindowanie się do nich poprzez mechanizmy frameworka. Przykładowe użycie customowego elementu może wyglądać nastepująco:

<aggregation-results id="aggs" if.bind="aggregationsData !== undefined">
    <h2>${selectedOption}</h2>
</aggregation-results>

Z jednej strony bindujemy się do propercji z ViewModelu żeby sterować widocznością, z drugiej wstawiamy do Web Componentu elementy stworzone poza Shadow DOM-em przy użyciu bindingu (do których będzie można odwołać się w samym komponencie).

Sam szablon zawiera w sobie widok, style i skrypt i wygląda następująco:

<template id="aggregation-results">
    <style>
        /*...*/
    </style>
    
    <div id="container">
        <content select="h2"></content>
        <table>
            <thead>
                <tr>
                    <th>Dzielnica</th>
                    <th>Min</th>
                    <th>Max</th>
                    <th>Średnia</th>
                </tr>
            </thead>
            <tbody id="districts-body"></tbody>
        </table>
    </div>    
</template>
<script>
    //...
</script>

Za pomocą taga content tworzy się insertion point dla elementów z zewnątrz. Pisząc style mamy dostęp do kilku nowych pseudoklas i pseudoselektorów:

<style>
    #container{
        background-color: #F3E6E8;
    }

    :host{
        margin-left: 100px;
    }

    ::content h2{
        font-size: 26px;
    }
</style>

 

:host pozwala nam ostylować element z light DOM hostujący nasz shadow DOM, natomiast ::content pozwala stylować te elementy, które wstawiamy przez tag content.

Założeniem Web Components jest to, że nie renderują się od razu w drzewie i trzeba je tam zarejestrować. Można to zrobić również w pliku z kompontentem poprzez IIFE jak poniżej:

(function() {
    var objectPrototype = Object.create(HTMLElement.prototype),
        selfDocument = document.currentScript.ownerDocument;
    Object.defineProperties(objectPrototype, {
        aggregations: {
            writable: true
        }
    });
    objectPrototype.createdCallback = function() {
        var shadow = this.createShadowRoot(),
            templateContent = selfDocument.querySelector('#aggregation-results').content,
            templateNodes = document.importNode(templateContent, true);
        shadow.appendChild(templateNodes);
        objectPrototype.tbody = shadow.querySelector("#districts-body");
    };

    objectPrototype.attributeChangedCallback = function (attrName, oldVal, newVal) {
        if (attrName === "aggregations") {
            //zbuduj elementy tabeli
        }
    }

    var aggregationResultsElement = document.registerElement("aggregation-results", {
        prototype: objectPrototype,

    });
})();

 

Sporo gotowych do użycia komponentów można znaleźć na przykład na stronie Polymera.

Advertisements

One thought on “[DajSięPoznać#8] Web Components i Aurelia

  1. Pingback: [DajSięPoznać] Podsumowanie | When the smoke is going down

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s