Elementy niestandardowe pozwalają twórcom stron internetowych definiować nowe tagi HTML, rozszerzać istniejące i tworzyć komponenty sieciowe wielokrotnego użytku.
Dzięki elementom niestandardowym programiści stron internetowych mogą tworzyć nowe tagi HTML, zwiększyć istniejące tagi HTML ani rozszerzyć komponentów utworzonych przez innych programistów. . Interfejs API stanowi podstawę internetu . Zapewnia dostęp do sieci oparte na standardowych rozwiązaniach do tworzenia komponentów wielokrotnego użytku vanilla JS/HTML/CSS. W efekcie uzyskamy mniej pisania i kodu modułowego oraz więcej możliwości ponownego wykorzystania nasze aplikacje.
Wprowadzenie
Przeglądarka jest doskonałym narzędziem do tworzenia struktury aplikacji internetowych. Jest o nazwie HTML. Być może już o tym słyszeliście. Jest poręczny, deklaratywny. i łatwą w obsłudze. Może być świetnym językiem HTML, a jego słownictwo możliwości rozszerzania są ograniczone. Nowy styl HTML standardem zawsze był sposób, automatycznie kojarzyj zachowanie JS ze znacznikami... do tej pory.
Niestandardowe elementy to odpowiedź na modernizację HTML a także łączenie ich z zachowaniem. Jeśli w kodzie HTML brakuje parametru rozwiązania problemu, możemy stworzyć element niestandardowy, który to robi. Niestandardowy uczą przeglądarki nowych sztuczek, zachowując przy tym zalety HTML.
Definiowanie nowego elementu
Aby zdefiniować nowy element HTML, potrzebujemy potęgi JavaScriptu.
Globalny customElements
jest używany do definiowania elementu niestandardowego i nauczania
o nowym tagu w przeglądarce. Wywołaj funkcję customElements.define()
i podaj nazwę tagu
które chcesz utworzyć, i kod JavaScript class
rozszerzający podstawę HTMLElement
.
Przykład – definiowanie mobilnego panelu szuflady, <app-drawer>
:
class AppDrawer extends HTMLElement {...}
window.customElements.define('app-drawer', AppDrawer);
// Or use an anonymous class if you don't want a named constructor in current scope.
window.customElements.define('app-drawer', class extends HTMLElement {...});
Przykład użycia:
<app-drawer></app-drawer>
Pamiętaj, że stosowanie elementu niestandardowego nie różni się
za pomocą elementu <div>
lub dowolnego innego elementu. Instancje można zadeklarować na stronie,
tworzone dynamicznie w JavaScripcie, można dołączać detektory zdarzeń. Keep
tutaj znajdziesz więcej przykładów.
Definiowanie interfejsu JavaScript API elementu
Funkcjonalność elementu niestandardowego jest określona w standardzie ES2015.
class
który obejmuje HTMLElement
. Rozszerzenie HTMLElement
zapewnia element niestandardowy
dziedziczy cały interfejs DOM API i oznacza wszelkie właściwości/metody dodane do
stają się częścią interfejsu DOM elementu. Zasadniczo użyj klasy do tego,
utwórz dla swojego tagu publiczny interfejs API JavaScript.
Przykład – definiowanie interfejsu DOM <app-drawer>
:
class AppDrawer extends HTMLElement {
// A getter/setter for an open property.
get open() {
return this.hasAttribute('open');
}
set open(val) {
// Reflect the value of the open property as an HTML attribute.
if (val) {
this.setAttribute('open', '');
} else {
this.removeAttribute('open');
}
this.toggleDrawer();
}
// A getter/setter for a disabled property.
get disabled() {
return this.hasAttribute('disabled');
}
set disabled(val) {
// Reflect the value of the disabled property as an HTML attribute.
if (val) {
this.setAttribute('disabled', '');
} else {
this.removeAttribute('disabled');
}
}
// Can define constructor arguments if you wish.
constructor() {
// If you define a constructor, always call super() first!
// This is specific to CE and required by the spec.
super();
// Setup a click listener on <app-drawer> itself.
this.addEventListener('click', e => {
// Don't toggle the drawer if it's disabled.
if (this.disabled) {
return;
}
this.toggleDrawer();
});
}
toggleDrawer() {
// ...
}
}
customElements.define('app-drawer', AppDrawer);
W tym przykładzie tworzymy szufladę z właściwością open
o nazwie disabled
.
i metodę toggleDrawer()
. Dodatkowo odzwierciedla właściwości jako HTML
.
Przydatną cechą elementów niestandardowych jest to, że element this
znajduje się w definicji klasy
odnosi się do samego elementu DOM, czyli instancji klasy. W naszym
np. this
odnosi się do <app-drawer>
. W ten sposób element może
Dołącz detektor click
do samego siebie. Nie musisz się ograniczać do detektorów zdarzeń.
Cały interfejs DOM API jest dostępny w kodzie elementu. Użyj adresu this
, aby uzyskać dostęp do
właściwości elementu, sprawdź jego elementy podrzędne (this.children
), węzły zapytania
(this.querySelectorAll('.items')
) itp.
Reguły tworzenia elementów niestandardowych
- Nazwa elementu niestandardowego musi zawierać myślnik (-). Dlatego
<x-tags>
,<my-element>
i<my-awesome-app>
to prawidłowe nazwy, a<tabs>
i<foo_bar>
nie. Dzięki temu parser HTML może odróżniać elementy niestandardowe od zwykłych. Zapewnia też gdy do kodu HTML dodano nowe tagi. - Nie możesz zarejestrować tego samego tagu więcej niż raz. Jeśli to zrobisz,
DOMException
. Poinformuj przeglądarkę o nowym tagu, . Bez cofnięcia się. - Elementów niestandardowych nie można samodzielnie zamykać, bo kod HTML zezwala tylko na kilka
elementy
do samozamknięcia. Zawsze zapisuj tag zamykający
(
<app-drawer></app-drawer>
).
Reakcje elementu niestandardowego
Element niestandardowy może definiować specjalne punkty zaczepienia cyklu życia do uruchamiania kodu podczas i w ciekawych czasach. Są to tak zwane elementy niestandardowe reakcji.
Nazwa | Wywoływane, gdy |
---|---|
constructor |
Wystąpienie elementu to
utworzonych lub uaktualnionych. Przydatne do inicjowania
jak skonfigurować detektory zdarzeń,
do tworzenia elementu shadow DOM.
Zobacz
spec
aby poznać ograniczenia dotyczące czynności, które możesz wykonywać w usłudze constructor .
|
connectedCallback |
Wywoływane za każdym razem, gdy który jest wstawiany do DOM. Przydaje się do uruchamiania kodu konfiguracji, takiego jak pobierania zasobów lub renderowania. Zazwyczaj należy opóźnić pracę do tego czasu. |
disconnectedCallback |
Wywoływana za każdym razem, gdy element jest usuwany z DOM. Przydatne dla podczas czyszczenia kodu. |
attributeChangedCallback(attrName, oldVal, newVal) |
Wywoływane po zaktualizowaniu zaobserwowanego atrybutu.
dodane, usunięte, zaktualizowane lub zastąpione. Występuje również w przypadku wartości początkowych
gdy element jest tworzony przez parser.
nowa. Tylko Uwaga:
atrybutów wymienionych we właściwości observedAttributes
oddzwonimy.
|
adoptedCallback |
element niestandardowy został przeniesiony do nowego elementu document (np.
osoba o nazwie document.adoptNode(el) ).
|
Wywołania zwrotne reakcji są synchroniczne. Jeśli ktoś dzwoni pod numer el.setAttribute()
dla elementu, przeglądarka od razu wywoła funkcję attributeChangedCallback()
.
Podobnie otrzymasz disconnectedCallback()
zaraz po tym, jak Twój element będzie
usuniętych z DOM (np. użytkownik wywołuje el.remove()
).
Przykład: dodawanie reakcji elementu niestandardowego do <app-drawer>
:
class AppDrawer extends HTMLElement {
constructor() {
super(); // always call super() first in the constructor.
// ...
}
connectedCallback() {
// ...
}
disconnectedCallback() {
// ...
}
attributeChangedCallback(attrName, oldVal, newVal) {
// ...
}
}
Określ reakcje, jeśli mają sens. Jeśli element jest wystarczająco złożony
i otwiera połączenie z IndexedDB w connectedCallback()
, wykonaj niezbędne
czyszczenie w disconnectedCallback()
. Zachowaj jednak ostrożność. Nie możesz polegać na
który jest usuwany z DOM we wszystkich okolicznościach. Przykład:
Funkcja disconnectedCallback()
nie zostanie nigdy wywołana, jeśli użytkownik zamknie kartę.
Właściwości i atrybuty
Właściwości odzwierciedlające atrybuty
Usługi HTML często odzwierciedlają swoją wartość z powrotem w DOM jako
Atrybut HTML. Na przykład, gdy wartości hidden
lub id
zostaną zmienione w
JS:
div.id = 'my-id';
div.hidden = true;
wartości są stosowane do aktywnego DOM jako atrybuty:
<div id="my-id" hidden>
Jest to tzw. „odzwierciedlenie właściwości atrybuty”. Tak jest w niemal każdej usłudze w kodzie HTML. Dlaczego? Atrybuty są też przydatne do: konfigurując element deklaratywny i określone interfejsy API, takie jak ułatwienia dostępu i CSS selektory zależą od atrybutów działania.
Odbicie właściwości jest przydatne wszędzie tam, gdzie chcesz zachować DOM elementu. zsynchronizowany ze stanem JavaScript. Dobrym pomysłem jest odzwierciedlają właściwość, więc po zmianie stanu JS styl zdefiniowany przez użytkownika jest stosowany.
Przypomnij sobie nasze <app-drawer>
. Konsument tego komponentu może chcieć go zanikać
lub uniemożliwiać użytkownikowi interakcję, gdy jest wyłączona:
app-drawer[disabled] {
opacity: 0.5;
pointer-events: none;
}
Gdy właściwość disabled
zostanie zmieniona w JS, chcemy, by atrybut ten
dodany do DOM, tak aby selektor użytkownika się zgadzał. Element może zapewnić,
zachowanie, odzwierciedlając wartość atrybutu o tej samej nazwie:
get disabled() {
return this.hasAttribute('disabled');
}
set disabled(val) {
// Reflect the value of `disabled` as an attribute.
if (val) {
this.setAttribute('disabled', '');
} else {
this.removeAttribute('disabled');
}
this.toggleDrawer();
}
Obserwowanie zmian atrybutów
Atrybuty HTML to wygodny sposób deklarowania przez użytkowników stanu początkowego:
<app-drawer open disabled></app-drawer>
Elementy mogą reagować na zmiany atrybutów, definiując atrybut
attributeChangedCallback
Przeglądarka będzie wywoływać tę metodę przy każdej zmianie
do atrybutów wymienionych w tablicy observedAttributes
.
class AppDrawer extends HTMLElement {
// ...
static get observedAttributes() {
return ['disabled', 'open'];
}
get disabled() {
return this.hasAttribute('disabled');
}
set disabled(val) {
if (val) {
this.setAttribute('disabled', '');
} else {
this.removeAttribute('disabled');
}
}
// Only called for the disabled and open attributes due to observedAttributes
attributeChangedCallback(name, oldValue, newValue) {
// When the drawer is disabled, update keyboard/screen reader behavior.
if (this.disabled) {
this.setAttribute('tabindex', '-1');
this.setAttribute('aria-disabled', 'true');
} else {
this.setAttribute('tabindex', '0');
this.setAttribute('aria-disabled', 'false');
}
// TODO: also react to the open attribute changing.
}
}
W przykładzie ustawiamy atrybuty dodatkowe w <app-drawer>
, gdy
Zmieniono atrybut disabled
. Chociaż nie zajmujemy się tym tutaj, możesz
Używaj też attributeChangedCallback
, by synchronizować właściwość JS ze swoim
.
Uaktualnianie elementów
Stopniowo ulepszony kod HTML
Wiedzieliśmy, że elementy niestandardowe definiuje się za pomocą funkcji
customElements.define()
Nie oznacza to jednak, że musisz zdefiniować i zarejestrować
elementu niestandardowego za jednym razem.
Elementów niestandardowych można używać przed zarejestrowaniem ich definicji.
Ulepszanie stopniowe to funkcja elementów niestandardowych. Innymi słowy,
zadeklarować kilka elementów <app-drawer>
na stronie i nigdy nie wywoływać
customElements.define('app-drawer', ...)
dużo później. To dlatego, że
przeglądarka inaczej traktuje potencjalne elementy niestandardowe dzięki nieznanej
. Proces wywoływania funkcji define()
i obdarowywania istniejącej
element z definicją klasy jest nazywany „uaktualnieniami elementu”.
Aby dowiedzieć się, kiedy zostanie zdefiniowana nazwa tagu, możesz użyć opcji
window.customElements.whenDefined()
Zwraca obietnicę rozwiązaną, gdy
.
customElements.whenDefined('app-drawer').then(() => {
console.log('app-drawer defined');
});
Przykład – opóźnienie pracy do momentu uaktualnienia zbioru elementów podrzędnych
<share-buttons>
<social-button type="twitter"><a href="...">Twitter</a></social-button>
<social-button type="fb"><a href="...">Facebook</a></social-button>
<social-button type="plus"><a href="...">G+</a></social-button>
</share-buttons>
// Fetch all the children of <share-buttons> that are not defined yet.
let undefinedButtons = buttons.querySelectorAll(':not(:defined)');
let promises = [...undefinedButtons].map((socialButton) => {
return customElements.whenDefined(socialButton.localName);
});
// Wait for all the social-buttons to be upgraded.
Promise.all(promises).then(() => {
// All social-button children are ready.
});
Treść zdefiniowana przez element
Elementy niestandardowe mogą zarządzać własną treścią za pomocą interfejsów DOM API kodu elementu. Bardzo przydają się do tego Reakcje.
Przykład – utwórz element z domyślnym kodem HTML:
customElements.define('x-foo-with-markup', class extends HTMLElement {
connectedCallback() {
this.innerHTML = "<b>I'm an x-foo-with-markup!</b>";
}
// ...
});
Zadeklarowanie tego tagu spowoduje:
<x-foo-with-markup>
<b>I'm an x-foo-with-markup!</b>
</x-foo-with-markup>
// DO ZROBIENIA: DevSite – przykładowy kod usunięty, ponieważ użyto wbudowanych modułów obsługi zdarzeń
Tworzenie elementu korzystającego z modelu Shadow DOM
Shadow DOM umożliwia elementowi posiadanie, wyrenderowanie i określenie stylu fragmentu DOM, który jest oddzielony od reszty strony. Aha, można nawet ukryć całą aplikację w jednym tagu:
<!-- chat-app's implementation details are hidden away in Shadow DOM. -->
<chat-app></chat-app>
Aby użyć modelu Shadow DOM w elemencie niestandardowym, wywołaj this.attachShadow
w
constructor
:
let tmpl = document.createElement('template');
tmpl.innerHTML = `
<style>:host { ... }</style> <!-- look ma, scoped styles -->
<b>I'm in shadow dom!</b>
<slot></slot>
`;
customElements.define('x-foo-shadowdom', class extends HTMLElement {
constructor() {
super(); // always call super() first in the constructor.
// Attach a shadow root to the element.
let shadowRoot = this.attachShadow({mode: 'open'});
shadowRoot.appendChild(tmpl.content.cloneNode(true));
}
// ...
});
Przykład użycia:
<x-foo-shadowdom>
<p><b>User's</b> custom text</p>
</x-foo-shadowdom>
<!-- renders as -->
<x-foo-shadowdom>
#shadow-root
<b>I'm in shadow dom!</b>
<slot></slot> <!-- slotted content appears here -->
</x-foo-shadowdom>
Niestandardowy tekst użytkownika
// DO ZROBIENIA: DevSite – przykładowy kod usunięty, ponieważ użyto wbudowanych modułów obsługi zdarzeń
Tworzenie elementów z: <template>
Jeśli nie znasz tych informacji, <template>
pierwiastek
umożliwia zadeklarowanie fragmentów DOM, które są analizowane i bezczynne podczas wczytywania strony oraz
można aktywować później w czasie działania. To kolejny podstawowy obiekt API w internecie
rodziny komponentów. Szablony są idealnym miejscem do zadeklarowania
w strukturze elementu niestandardowego.
Przykład: zarejestrowanie elementu z treścią Shadow DOM utworzoną na podstawie
<template>
:
<template id="x-foo-from-template">
<style>
p { color: green; }
</style>
<p>I'm in Shadow DOM. My markup was stamped from a <template>.</p>
</template>
<script>
let tmpl = document.querySelector('#x-foo-from-template');
// If your code is inside of an HTML Import you'll need to change the above line to:
// let tmpl = document.currentScript.ownerDocument.querySelector('#x-foo-from-template');
customElements.define('x-foo-from-template', class extends HTMLElement {
constructor() {
super(); // always call super() first in the constructor.
let shadowRoot = this.attachShadow({mode: 'open'});
shadowRoot.appendChild(tmpl.content.cloneNode(true));
}
// ...
});
</script>
Te kilka linijek kodu to nie lada wyzwanie. Dowiedzmy się, dnia:
- Definiujemy nowy element w kodzie HTML:
<x-foo-from-template>
- Model Shadow DOM elementu jest tworzony na podstawie modelu
<template>
. - DOM elementu jest lokalny dzięki interfejsowi Shadow DOM.
- Wewnętrzny kod CSS elementu jest ograniczony do niego dzięki interfejsowi Shadow DOM.
Korzystam z Shadow DOM. Moje znaczniki zostały opatrzone pieczęcią z szablonu <template>.
// DO ZROBIENIA: DevSite – przykładowy kod usunięty, ponieważ użyto wbudowanych modułów obsługi zdarzeń
Określanie stylu elementu niestandardowego
Nawet jeśli element definiuje swój własny styl za pomocą modelu Shadow DOM, użytkownicy mogą do Twojego elementu niestandardowego. Są to tak zwane „style zdefiniowane przez użytkownika”.
<!-- user-defined styling -->
<style>
app-drawer {
display: flex;
}
panel-item {
transition: opacity 400ms ease-in-out;
opacity: 0.3;
flex: 1;
text-align: center;
border-radius: 50%;
}
panel-item:hover {
opacity: 1.0;
background: rgb(255, 0, 255);
color: white;
}
app-panel > panel-item {
padding: 5px;
list-style: none;
margin: 0 7px;
}
</style>
<app-drawer>
<panel-item>Do</panel-item>
<panel-item>Re</panel-item>
<panel-item>Mi</panel-item>
</app-drawer>
Możesz zadawać sobie pytanie, jak działa szczegółowość CSS, jeśli element ma style zdefiniowane w modelu Shadow DOM. Jeśli chodzi o konkretność, najważniejsze są style użytkownika. Będą zawsze zastępują styl zdefiniowany przez element. Zobacz sekcję Tworzenie elementu który korzysta z modelu Shadow DOM.
Wstępne dostosowywanie stylu niezarejestrowanych elementów
Przed uaktualnieniem elementu możesz kierować na niego reklamy w CSS za pomocą
Pseudoklasa :defined
. Jest to przydatne przy wstępnym określaniu stylu komponentu. Dla:
np. zapobiec układowi lub innemu elementowi wizualnemu funkcji FOUC, ukrywając niezdefiniowane
i zanikanie w momencie, gdy są zdefiniowane.
Przykład – ukryj <app-drawer>
przed zdefiniowaniem:
app-drawer:not(:defined) {
/* Pre-style, give layout, replicate app-drawer's eventual styles, etc. */
display: inline-block;
height: 100vh;
opacity: 0;
transition: opacity 0.3s ease-in-out;
}
Po zdefiniowaniu parametru <app-drawer>
selektor (app-drawer:not(:defined)
)
już nie pasuje.
Przedłużanie elementów
Interfejs Custom Elements API przydaje się do tworzenia nowych elementów HTML, ale pozwala też przydatny do rozszerzania innych elementów niestandardowych, a nawet wbudowanego kodu HTML przeglądarki.
Rozszerzanie elementu niestandardowego
Kolejny element niestandardowy można rozszerzyć przez rozszerzenie jego definicji klasy.
Przykład – utwórz typ <fancy-app-drawer>
, który obejmuje rozszerzenie <app-drawer>
:
class FancyDrawer extends AppDrawer {
constructor() {
super(); // always call super() first in the constructor. This also calls the extended class' constructor.
// ...
}
toggleDrawer() {
// Possibly different toggle implementation?
// Use ES2015 if you need to call the parent method.
// super.toggleDrawer()
}
anotherMethod() {
// ...
}
}
customElements.define('fancy-app-drawer', FancyDrawer);
Rozciąganie natywnych elementów HTML
Załóżmy, że chcesz utworzyć bardziej wymyślny produkt <button>
. Zamiast powielać
zachowanie i funkcjonalność <button>
, lepszym rozwiązaniem jest stopniowe wprowadzanie
ulepszyć istniejący element za pomocą elementów niestandardowych.
Niestandardowy element wbudowany to niestandardowy element, który stanowi rozszerzenie jednego z wbudowanych tagów HTML przeglądarki. Główną korzyścią jest przedłużenie uzyskać wszystkie swoje cechy (właściwości DOM, metody, ułatwienia dostępu). Nie ma lepszego sposobu na stworzenie progresywnej sieci app, a nie stopniowo ulepszaj istniejący kod HTML. .
Aby rozszerzyć element, musisz utworzyć definicję klasy, która dziedziczy
z odpowiedniego interfejsu DOM. Przykładem może być element niestandardowy, który rozciąga się
Funkcja <button>
musi dziedziczyć z reguły HTMLButtonElement
zamiast HTMLElement
.
Analogicznie element rozszerzający <img>
musi być dłuższy niż HTMLImageElement
.
Przykład – rozszerzenie <button>
:
// See https://html.spec.whatwg.org/multipage/indices.html#element-interfaces
// for the list of other DOM interfaces.
class FancyButton extends HTMLButtonElement {
constructor() {
super(); // always call super() first in the constructor.
this.addEventListener('click', e => this.drawRipple(e.offsetX, e.offsetY));
}
// Material design ripple animation.
drawRipple(x, y) {
let div = document.createElement('div');
div.classList.add('ripple');
this.appendChild(div);
div.style.top = `${y - div.clientHeight/2}px`;
div.style.left = `${x - div.clientWidth/2}px`;
div.style.backgroundColor = 'currentColor';
div.classList.add('run');
div.addEventListener('transitionend', (e) => div.remove());
}
}
customElements.define('fancy-button', FancyButton, {extends: 'button'});
Zwróć uwagę, że wywołanie metody define()
nieco się zmienia po rozszerzeniu reklamy natywnej
. Wymagany trzeci parametr informuje przeglądarkę, o którym tagu
i rozszerzenia. Jest to konieczne, ponieważ wiele tagów HTML korzysta z tego samego DOM
za pomocą prostego interfejsu online. <section>
, <address>
, i <em>
(między innymi) mają taki sam udział
HTMLElement
; <q>
i <blockquote>
współużytkują HTMLQuoteElement
; itp...
Jeśli określisz {extends: 'blockquote'}
, przeglądarka będzie wiedzieć, że tworzysz plik
uzupełnione <blockquote>
zamiast <q>
. Przeczytaj kod HTML
spec
gdzie znajdziesz pełną listę interfejsów DOM HTML.
Klienci korzystający z dostosowanego wbudowanego elementu mogą korzystać z niego na kilka sposobów. Mogą
zadeklaruj go, dodając atrybut is=""
w tagu natywnym:
<!-- This <button> is a fancy button. -->
<button is="fancy-button" disabled>Fancy button!</button>
utwórz instancję w kodzie JavaScript:
// Custom elements overload createElement() to support the is="" attribute.
let button = document.createElement('button', {is: 'fancy-button'});
button.textContent = 'Fancy button!';
button.disabled = true;
document.body.appendChild(button);
lub użyj operatora new
:
let button = new FancyButton();
button.textContent = 'Fancy button!';
button.disabled = true;
Oto kolejny przykład z rozszerzeniem <img>
.
Przykład – rozszerzenie <img>
:
customElements.define('bigger-img', class extends Image {
// Give img default size if users don't specify.
constructor(width=50, height=50) {
super(width * 10, height * 10);
}
}, {extends: 'img'});
Użytkownicy deklarują ten komponent jako:
<!-- This <img> is a bigger img. -->
<img is="bigger-img" width="15" height="20">
lub utwórz instancję w kodzie JavaScript:
const BiggerImage = customElements.get('bigger-img');
const image = new BiggerImage(15, 20); // pass constructor values like so.
console.assert(image.width === 150);
console.assert(image.height === 200);
Różne szczegóły
Nieznane elementy a niezdefiniowane elementy niestandardowe
Kod HTML jest łatwy w obsłudze i elastyczny. Na przykład zadeklaruj
<randomtagthatdoesntexist>
na stronie, a przeglądarka jest całkowicie zadowolona
akceptacja tego zaproszenia. Dlaczego działają tagi niestandardowe? Odpowiedź brzmi: HTML
specyfikacja
na to zezwala. Elementy, które nie są zdefiniowane w specyfikacji, są analizowane jako
HTMLUnknownElement
To samo nie dotyczy elementów niestandardowych. Analiza potencjalnych elementów niestandardowych
jako HTMLElement
, jeśli zostały utworzone z prawidłową nazwą (ze znakiem „-”). Ty
możesz sprawdzić to w przeglądarce, która obsługuje elementy niestandardowe. Uruchom konsolę:
Ctrl+Shift+J (lub Cmd+Opt+J na Macu) i wklej
następujące wiersze kodu:
// "tabs" is not a valid custom element name
document.createElement('tabs') instanceof HTMLUnknownElement === true
// "x-tabs" is a valid custom element name
document.createElement('x-tabs') instanceof HTMLElement === true
Dokumentacja API
Globalna wartość customElements
definiuje przydatne metody pracy z niestandardową
.
define(tagName, constructor, options)
Definiuje nowy element niestandardowy w przeglądarce.
Przykład
customElements.define('my-app', class extends HTMLElement { ... });
customElements.define(
'fancy-button', class extends HTMLButtonElement { ... }, {extends: 'button'});
get(tagName)
Po podaniu prawidłowej nazwy tagu elementu niestandardowego zwraca konstruktor elementu.
Zwraca wartość undefined
, jeśli nie zarejestrowano żadnej definicji elementu.
Przykład
let Drawer = customElements.get('app-drawer');
let drawer = new Drawer();
whenDefined(tagName)
Zwraca obietnicę obowiązującą po zdefiniowaniu elementu niestandardowego. Jeśli Element jest już zdefiniowany, zastosuj natychmiast. Odrzuca, jeśli nazwa tagu nie jest prawidłowa prawidłową nazwę elementu niestandardowego.
Przykład
customElements.whenDefined('app-drawer').then(() => {
console.log('ready!');
});
Obsługa historii i przeglądarki
Jeśli od kilku lat obserwujesz komponenty sieciowe,
że w Chrome w wersji 36 lub nowszej została zaimplementowana wersja interfejsu Custom Elements API
document.registerElement()
zamiast customElements.define()
. To teraz
uznano za wycofaną wersję standardu o nazwie v0.
customElements.define()
to nowa popularność i dostawcy przeglądarek
w Twojej firmie. Nosi ona nazwę „Elementy niestandardowe w wersji 1”.
Jeśli interesuje Cię stara specyfikacja v0, sprawdź html5rocks .
Obsługa przeglądarek
Chrome 54 (stan), Safari 10.1 (stan) i Firefox 63 (stan): Elementy niestandardowe w wersji 1. Edge rozpoczął się .
Aby funkcja wykrywała elementy niestandardowe, sprawdź, czy istnieją
window.customElements
:
const supportsCustomElementsV1 = 'customElements' in window;
Watolina
Dopóki obsługa przeglądarek nie stanie się powszechnie dostępna, samodzielna reklama polyfill dostępne w przypadku elementów niestandardowych w wersji 1. Zalecamy jednak korzystanie z pliku webcomponents.js loader aby optymalnie wczytywać elementy polyfill komponentów internetowych. Moduł ładujący korzysta z wykrywania cech, aby asynchronicznie wczytywać tylko niezbędne wypełnienia wymagane przez przeglądarkę.
Zainstaluj:
npm install --save @webcomponents/webcomponentsjs
Sposób użycia:
<!-- Use the custom element on the page. -->
<my-element></my-element>
<!-- Load polyfills; note that "loader" will load these async -->
<script src="node_modules/@webcomponents/webcomponentsjs/webcomponents-loader.js" defer></script>
<!-- Load a custom element definitions in `waitFor` and return a promise -->
<script type="module">
function loadScript(src) {
return new Promise(function(resolve, reject) {
const script = document.createElement('script');
script.src = src;
script.onload = resolve;
script.onerror = reject;
document.head.appendChild(script);
});
}
WebComponents.waitFor(() => {
// At this point we are guaranteed that all required polyfills have
// loaded, and can use web components APIs.
// Next, load element definitions that call `customElements.define`.
// Note: returning a promise causes the custom elements
// polyfill to wait until all definitions are loaded and then upgrade
// the document in one batch, for better performance.
return loadScript('my-element.js');
});
</script>
Podsumowanie
Elementy niestandardowe dają nam nowe narzędzie do definiowania nowych tagów HTML w przeglądarce
tworzenie komponentów wielokrotnego użytku. Połącz je z inną nową platformą
elementów podstawowych, takich jak Shadow DOM czy <template>
. Zaczynamy zdawać sobie sprawę,
obraz komponentów sieciowych:
- Wiele przeglądarek (standard internetowy) do tworzenia i rozszerzania komponentów wielokrotnego użytku.
- Aby zacząć, nie musisz korzystać z biblioteki ani platformy. Wanilla JS/HTML FTW!
- Udostępnia znany model programowania. To po prostu DOM/CSS/HTML.
- Współpracuje z innymi nowymi funkcjami platformy internetowej (Shadow DOM,
<template>
, CSS) właściwości niestandardowe itd.) - Ścisła integracja z Narzędziami deweloperskimi w przeglądarce.
- Wykorzystaj istniejące ułatwienia dostępu.