Dzięki elementom niestandardowym możesz tworzyć własne tagi HTML. Ta lista kontrolna obejmuje sprawdzone metody tworzenia elementów wysokiej jakości.
Elementy niestandardowe umożliwiają rozszerzanie kodu HTML i definiowanie własnych tagów. Są
ale są też mało zaawansowane, co oznacza, że
zawsze jasne, jak najlepiej wdrożyć własny element.
Aby zapewnić Ci jak najlepsze wrażenia, opracowaliśmy
listę kontrolną. Ten raport zawiera wszystko, co naszym zdaniem jest potrzebne do
dobrze działający element niestandardowy.
Lista kontrolna
Shadow DOM
Utwórz pierwiastek cienia, aby uwzględnić style. |
Why? |
Umieszczając style w głównym cieniu elementu, masz pewność, że będą one działać.
niezależnie od tego, gdzie są używane. Jest to szczególnie ważne, jeśli programista
chce umieścić element wewnątrz rdzenia cienia innego elementu. Ten
Dotyczy to nawet prostych elementów, takich jak pole wyboru czy przycisk. Może to być
w przypadku gdy jedyną treścią wewnątrz cienia głównego będą style
się dowiedzieć.
|
Przykład |
<howto-checkbox> .
|
Utwórz w konstruktorze pierwiastek cienia.
|
Why? |
Konstruktor polega na tym, że dysponujesz wyłączną wiedzą na temat elementu.
To dobry moment na skonfigurowanie szczegółów implementacji, które nie powinny być
bałaganów. Czynność ta zostanie wykonana podczas późniejszego wywołania zwrotnego, takiego jak
connectedCallback , oznacza, że musisz zabezpieczyć się przed
gdy element jest odłączony, a następnie ponownie dołączany do dokumentu.
|
Przykład |
<howto-checkbox> .
|
Umieść wszystkie elementy podrzędne utworzone przez element w jego rdzeniu cienia.
|
Why? |
Elementy podrzędne tworzone przez Twój element są częścią jego implementacji i powinny
prywatne. Bez ochrony rdzenia cienia kod JavaScript może
nieumyślnie przeszkadzały tym dzieciom.
|
Przykład |
<howto-tabs> .
|
Użyj <slot> aby umieścić elementy podrzędne DOM Light w modelu Shadow DOM.
|
Why? |
Jeśli zezwolisz użytkownikom komponentu na określenie treści jako elementów podrzędnych HTML, będzie on bardziej kompozycyjny. Jeśli przeglądarka nie obsługuje elementów niestandardowych, zagnieżdżona treść pozostaje dostępna, widoczna i dostępna.
|
Przykład |
<howto-tabs> .
|
Ustaw styl wyświetlania w polu :host (np. block ,
inline-block , flex ), chyba że wolisz użyć domyślnej
inline .
|
Why? |
Domyślna wartość elementów niestandardowych to display: inline , więc ustawienie ich
width lub height nie będą miały żadnego efektu. Często
jest niespodzianką dla programistów i może powodować problemy związane
układając stronę. O ile nie wolisz wyświetlacza inline ,
zawsze powinien mieć ustawioną domyślną wartość display .
|
Przykład |
<howto-checkbox> .
|
Dodaj styl wyświetlania :host , który uwzględnia ukryty atrybut.
|
Why? |
Element niestandardowy z domyślnym stylem display , np.
:host { display: block } , zastąpi mniejszą szczegółowość
wbudowane
hidden .
Może to Cię zaskoczyć, jeśli spodziewasz się ustawienia atrybutu hidden
w elemencie, by renderować go display: none . Dodatkowo
do domyślnego stylu display , dodaj obsługę stylu hidden
dzięki funkcji :host([hidden]) { display: none } .
|
Przykład |
<howto-checkbox> .
|
Atrybuty i właściwości
Nie zastępuj atrybutów globalnych ustawionych przez autora.
|
Why? |
Atrybuty globalne to atrybuty, które występują we wszystkich elementach HTML. Niektóre
np. tabindex i role . Element niestandardowy
może ustawić początkowy tabindex na 0, aby to był klawiatura
które można zaznaczyć. Zawsze jednak należy najpierw sprawdzić, czy programista
Twój element ustawił inną wartość. Jeśli na przykład ustawili
tabindex do -1, jest to sygnał, że klient nie chce
do elementu interaktywnego.
|
Przykład |
<howto-checkbox> . Szczegółowo wyjaśniliśmy to w
Nie zastępuj autora strony.
|
Zawsze akceptuj podstawowe dane (ciągi znaków, liczby, wartości logiczne) jako dowolny atrybut
lub właściwości.
|
Why? |
Elementy niestandardowe, tak jak ich wbudowane odpowiedniki, powinny dawać się konfigurować.
Konfiguracja można przekazywać deklaratywnie, za pomocą atrybutów lub imperatywnie
za pomocą właściwości JavaScript. Najlepiej, gdyby każdy atrybut był również powiązany z
z odpowiednią usługą.
|
Przykład |
<howto-checkbox> .
|
Dąż do synchronizacji atrybutów i właściwości podstawowych danych, odzwierciedlając
do atrybutu i odwrotnie.
|
Why? |
Nigdy nie wiadomo, jak użytkownik zareaguje na Twój element. Może
ustawić właściwość w JavaScript, a następnie odczytać tę wartość
za pomocą interfejsu API takiego jak getAttribute() . Jeśli każdy atrybut ma atrybut
i odzwierciedlają oba te elementy, ułatwi
do pracy z elementem. Innymi słowy,
setAttribute('foo', value) powinien też ustawić odpowiednią wartość
foo i odwrotnie. Oczywiście istnieją oczywiście wyjątki,
tę regułę. Nie należy odzwierciedlać właściwości o dużej częstotliwości, np.
currentTime w odtwarzaczu. Kieruj się własną oceną. Jeśli
sprawia wrażenie, że użytkownik wchodzi w interakcję z właściwością lub atrybutem oraz
odzwierciedlenie tego faktu nie jest męczące.
|
Przykład |
<howto-checkbox> . Szczegółowo wyjaśniliśmy to w
Unikaj problemów z ponownym wyświetlaniem.
|
Staraj się akceptować tylko dane sformatowane (obiekty, tablice) jako właściwości.
|
Why? |
Zasadniczo nie ma przykładów wbudowanych elementów HTML, które
Akceptuj dane rozszerzone (zwykłe obiekty i tablice JavaScript) za pomocą
. Dane rozszerzone są akceptowane przez wywołania metody lub
usług. Akceptowanie danych rozszerzonych jako
zserializowanie dużego obiektu do ciągu znaków może być kosztowne,
wszystkie odwołania do obiektów zostaną utracone w trakcie tego procesu wprowadzania ciągu znaków. Dla:
Ciąg znaków z obiektu, który odwołuje się do innego obiektu,
lub węzła DOM, odwołania te zostaną utracone.
|
Nie odzwierciedlaj rozszerzonych właściwości danych w atrybutach.
|
Why? |
przekształcanie szczegółowych właściwości danych w atrybuty jest niepotrzebnie kosztowne,
wymaga serializacji i deserializacji tych samych obiektów JavaScript. O ile
masz przypadek użycia, który da się rozwiązać tylko za pomocą tej funkcji,
najlepiej będzie ich unikać.
|
Rozważ sprawdzenie właściwości, które mogły zostać ustawione przed elementem.
uaktualniono.
|
Why? |
Programista korzystający z Twojego elementu może próbować ustawić jego właściwość.
przed załadowaniem jego definicji. Dotyczy to zwłaszcza sytuacji, gdy
Deweloper używa platformy, która zajmuje się wczytywaniem komponentów, oznaczaniem ich
i powiąż ich właściwości z modelem.
|
Przykład |
<howto-checkbox> . Bardziej szczegółowe informacje:
Ustawianie właściwości jako leniwe.
|
Nie zgłaszaj zajęć samodzielnie.
|
Why? |
Elementy, które muszą określać swój stan, powinny to robić za pomocą atrybutów.
Uznaje się, że atrybut class należy do
używając Twojego elementu i przez pomyłkę wpisanie do niego kodu
iść na zajęcia z programowania.
|
Wydarzenia
Wysyłanie zdarzeń w odpowiedzi na działanie komponentu wewnętrznego.
|
Why? |
Komponent może mieć właściwości, które zmieniają się w odpowiedzi na działanie,
tylko komponent wie o
lub gdy zasób zostanie wczytany. Warto wysyłać zdarzenia
w odpowiedzi na te zmiany, aby powiadomić hosta, że stan komponentu to
w inny sposób.
|
Nie wysyłaj zdarzeń w odpowiedzi na ustawienie właściwości przez hosta (w dół
przepływu danych).
|
Why? |
Wysyłanie zdarzenia w odpowiedzi na ustawienie hosta w usłudze jest niepotrzebne
(gospodarz zna bieżący stan, ponieważ go ustawił). Zdarzenia wysyłania
w odpowiedzi na ustawienie hosta usługa może powodować nieskończoną pętlę danych
systemów wiążących.
|
Przykład |
<howto-checkbox> .
|
Filmy objaśniające
Nie zastępuj autora strony
Może się zdarzyć, że programista używający Twojego elementu będzie chciał zastąpić część
stanie początkowym. Na przykład zmiana ARIA role
lub zaznaczenia za pomocą
tabindex
Sprawdź, czy ustawiono te i inne atrybuty globalne.
przed zastosowaniem własnych wartości.
connectedCallback() {
if (!this.hasAttribute('role'))
this.setAttribute('role', 'checkbox');
if (!this.hasAttribute('tabindex'))
this.setAttribute('tabindex', 0);
Ustaw właściwości jako leniwe
Programista może spróbować ustawić właściwość w elemencie, zanim jego
definicja została wczytana. Zwłaszcza wtedy, gdy deweloper korzysta z
która obsługuje wczytywanie komponentów i umieszczanie ich na stronie,
ich właściwości z modelem.
W tym przykładzie Angular deklaratywnie wiąże model swojego modelu
właściwość isChecked
do właściwości checked
pola wyboru. Jeśli definicja zapytania
pole wyboru instrukcji zostało leniwie ładowane, możliwe, że Angular próbował ustawić
zaznaczoną właściwość przed uaktualnieniem elementu.
<howto-checkbox [checked]="defaults.isChecked"></howto-checkbox>
W tym scenariuszu element niestandardowy powinien sprawdzać, czy jakieś właściwości mają
została już ustawiona w instancji. <howto-checkbox>
demonstruje ten wzorzec przy użyciu metody o nazwie _upgradeProperty()
.
connectedCallback() {
...
this._upgradeProperty('checked');
}
_upgradeProperty(prop) {
if (this.hasOwnProperty(prop)) {
let value = this[prop];
delete this[prop];
this[prop] = value;
}
}
_upgradeProperty()
przechwytuje wartość z nieuaktualnionej instancji i usuwa
właściwości, tak aby nie powielała ona metody ustawiającej właściwości elementu niestandardowego.
Dzięki temu, gdy definicja elementu w końcu zostanie wczytana, może od razu
będą odzwierciedlać właściwy stan.
Unikanie problemów z ponownym wyświetlaniem
Może łatwo odzwierciedlić stan w polu attributeChangedCallback()
usługi bazowej, na przykład:
// When the [checked] attribute changes, set the checked property to match.
attributeChangedCallback(name, oldValue, newValue) {
if (name === 'checked')
this.checked = newValue;
}
Może to jednak spowodować nieskończoną pętlę, jeśli licytujący będzie też odzwierciedlić
atrybut.
set checked(value) {
const isChecked = Boolean(value);
if (isChecked)
// OOPS! This will cause an infinite loop because it triggers the
// attributeChangedCallback() which then sets this property again.
this.setAttribute('checked', '');
else
this.removeAttribute('checked');
}
Można też zezwolić na odzwierciedlenie przez narzędzie ustawiające właściwości w odniesieniu do atrybutu,
deweloper określi jego wartość na podstawie atrybutu.
set checked(value) {
const isChecked = Boolean(value);
if (isChecked)
this.setAttribute('checked', '');
else
this.removeAttribute('checked');
}
get checked() {
return this.hasAttribute('checked');
}
W tym przykładzie dodanie lub usunięcie atrybutu spowoduje ustawienie właściwości.
attributeChangedCallback()
może też służyć do obsługi efektów ubocznych.
np. stosowanie stanów ARIA.
attributeChangedCallback(name, oldValue, newValue) {
const hasValue = newValue !== null;
switch (name) {
case 'checked':
// Note the attributeChangedCallback is only handling the *side effects*
// of setting the attribute.
this.setAttribute('aria-checked', hasValue);
break;
...
}
}