Vanilla JavaScript i natywne API DOM jako alternatywa dla Reacta i innych frameworków

Spis treści
Vanilla JavaScript oznacza korzystanie z JavaScriptu i API przeglądarki bez dodatkowej biblioteki interfejsu. W małym kalkulatorze, wskaźniku stanu lub niezależnym narzędziu na stronie takie podejście może ograniczyć zależności i pobierany kod. W aplikacji ze współdzielonym stanem, routingiem i wieloma powiązanymi widokami framework może zapewnić przydatną strukturę. Decyzja zależy od interfejsu i kosztu utrzymania, a nie od uniwersalnego rankingu szybkości.
Koszty renderowania wymagają pomiarów
React podczas renderowania wyznacza oczekiwany interfejs, a następnie wprowadza potrzebne zmiany w DOM. Obliczanie układu i malowanie pozostają zadaniami przeglądarki. React, Angular i Vue nie stosują jednego identycznego mechanizmu aktualizacji. Hydratacja dołącza zachowanie klienta do HTML wygenerowanego na serwerze; nie każda aplikacja korzysta z hydratacji.
Duże skrypty i długie zadania synchroniczne mogą opóźniać interakcje w obu architekturach. Bezpośredni dostęp do DOM również może wywołać kosztowne obliczenia układu, zwłaszcza przy naprzemiennym odczytywaniu i zmienianiu geometrii. Usunięcie biblioteki nie usuwa pracy wykonywanej przez aplikację.
LCP opisuje moment wyrenderowania największego kwalifikującego się widocznego elementu treści. Znaczenie mogą mieć odpowiedź serwera, obrazy, fonty, CSS i JavaScript. INP opisuje responsywność interakcji podczas wizyty na stronie. Mniejsze pakiety mogą pomóc, ale liczba zależności ani CSS Grid nie gwarantują dobrych wyników. Porównanie wymaga takich samych funkcji, reprezentatywnych urządzeń, diagnostyki laboratoryjnej i pomiarów z rzeczywistych wizyt.

Natywne elementy konstrukcyjne
- Semantyczny HTML: natywne przyciski, pola formularzy i rozwijane sekcje stanowią dobry punkt wyjścia przed własnymi skryptami.
- Custom elements: elementy wielokrotnego użytku mogą reagować na dołączenie i zmiany atrybutów. Opcjonalny Shadow DOM wydziela wewnętrzne drzewo oraz style; custom element nie wymaga Shadow DOM.
- Szablony: zwykły
<template>przechowuje nieaktywny fragment do klonowania. Klonowanie i wstawianie dużego drzewa nadal zajmuje czas. - Delegacja zdarzeń: kontener może obsługiwać odpowiednie zdarzenia potomków propagujące w górę. Zdarzenia bez takiej propagacji i granice Shadow DOM wymagają osobnego uwzględnienia.
Te funkcje należą do standardów HTML i DOM. ECMAScript definiuje język JavaScript, a nie cały model komponentów przeglądarki.
Wskaźnik z jawną obsługą stanu
Poniższy komponent light DOM zarządza własną zawartością potomną i przyjmuje wyłącznie idle, ready oraz error. Nieznane wartości dają idle. Zmiany atrybutu aktualizują widoczny tekst po wstawieniu elementu, a ponowne dołączenie zachowuje istniejące węzły.
class CustomStatusBadge extends HTMLElement {
static observedAttributes = ['data-status'];
connectedCallback() {
if (!this.badge) {
this.badge = document.createElement('span');
this.dot = document.createElement('span');
this.dot.className = 'dot';
this.dot.setAttribute('aria-hidden', 'true');
this.label = document.createElement('span');
this.label.className = 'label';
this.badge.append(this.dot, this.label);
this.replaceChildren(this.badge);
}
this.render();
}
attributeChangedCallback() {
if (this.badge) this.render();
}
render() {
const raw = this.getAttribute('data-status');
const status = ['idle', 'ready', 'error'].includes(raw) ? raw : 'idle';
this.badge.className = 'badge badge-' + status;
this.label.textContent = 'Status: ' + status.toUpperCase();
}
}
customElements.define('status-badge', CustomStatusBadge);
Rejestracja następuje raz, najlepiej w zewnętrznym module. Przykładowy HTML: <status-badge data-status="ready">Status: READY</status-badge>. Tekst zastępczy jest dostępny przed uruchomieniem modułu. Style .badge, .dot i klas stanu zależą od aplikacji. Angielskie etykiety przykładu wymagają lokalizacji w interfejsie wielojęzycznym.
Budowanie DOM nie wymaga parsowania ciągu HTML, a textContent wstawia tekst. Lista dozwolonych wartości zapobiega także dodawaniu obcych klas CSS przez dowolne wartości stanu. To lokalna reguła komponentu, a nie pełna polityka bezpieczeństwa: adresy URL, formatowany HTML i inne konteksty wyjściowe wymagają odpowiedniej obsługi. Ozdobna kropka jest ukryta przed technologiami asystującymi; tekst przekazuje stan niezależnie od koloru. Automatyczne ogłaszanie zmian wymaga świadomie zaprojektowanego i przetestowanego regionu live.
Pytania i odpowiedzi
Kiedy framework jest opłacalny?
Stan współdzielony między wieloma widokami, złożona nawigacja, konwencje zespołu i gotowe dostępne komponenty mogą uzasadniać bibliotekę. Obok kosztu ładowania liczą się utrzymanie i poprawność. Niezależne narzędzia często potrzebują mniej infrastruktury; duża aplikacja nie staje się automatycznie prostsza po usunięciu zależności.
Czy Shadow DOM wysyła wewnętrzne pole z zewnętrznym formularzem?
Pole wewnątrz drzewa Shadow DOM nie należy automatycznie do zewnętrznego formularza. Element powiązany z formularzem może wykorzystać ElementInternals i setFormValue. Walidacja, resetowanie, etykiety i obsługa klawiatury nadal wymagają implementacji oraz testów. Natywne pola pozostają wartościową opcją.
Czy escapowanie we frameworku zapobiega każdemu wstrzyknięciu kodu?
Nie. Zwykła interpolacja tekstu i jawne API surowego HTML działają inaczej. Wskaźnik korzysta ze wstawiania tekstu oraz stałych klas; dowolny niezaufany HTML nie może być traktowany jak zwykła interpolacja tekstu.
Źródła
- React: Render and Commit
- React: hydrateRoot – Hydrating server-rendered HTML
- Angular: Component Lifecycle
- Google web.dev: Interaction to Next Paint (INP)
- Google web.dev: Largest Contentful Paint (LCP)
- WHATWG HTML Standard: Custom elements
- WHATWG HTML Standard: The template element
- WHATWG DOM Standard: Node.textContent
- MDN Web Docs: Web technology reference
- Google web.dev: Avoid large, complex layouts and layout thrashing
- React: Dangerously setting the inner HTML