4.3 KiB
4.3 KiB
Fragment Re-rendering
System fragment re-rendering pozwala na selektywne przeładowywanie części DOM bez konieczności re-renderowania całego komponentu.
Jak to działa
Każdy ng-container w template jest zastępowany parą komentarzy-markerów:
<!-- Przed przetworzeniem -->
<ng-container *ngIf="showDetails">
<div>Szczegóły</div>
</ng-container>
<!-- Po przetworzeniu w DOM -->
<!--ng-container-start *ngIf="showDetails"-->
<div>Szczegóły</div>
<!--ng-container-end-->
Zalety
- Widoczność w DevTools - możesz zobaczyć w DOM gdzie był
ng-container - Selektywne re-renderowanie - możesz przeładować tylko fragment zamiast całego komponentu
- Zachowanie struktury - markery pokazują dokładne granice fragmentu
- Debugowanie - łatwiej śledzić które fragmenty są renderowane
API
Pobranie TemplateFragment
const appRoot = document.querySelector('app-root') as any;
const templateFragment = appRoot.templateFragment;
Pobranie informacji o markerach
const markers = templateFragment.getFragmentMarkers();
// Zwraca tablicę obiektów:
// {
// startMarker: Comment, // Komentarz początkowy
// endMarker: Comment, // Komentarz końcowy
// condition?: string, // Warunek *ngIf (jeśli istnieje)
// originalTemplate: string // Oryginalny HTML fragmentu
// }
Re-renderowanie konkretnego fragmentu
// Re-renderowanie fragmentu po indeksie
templateFragment.rerenderFragment(0);
// Lub znalezienie fragmentu po warunku
const markers = templateFragment.getFragmentMarkers();
const index = markers.findIndex(m => m.condition?.includes('showDetails'));
if (index >= 0) {
templateFragment.rerenderFragment(index);
}
Re-renderowanie wszystkich fragmentów
templateFragment.rerenderAllFragments();
Przykłady użycia
Przykład 1: Toggle visibility
// Komponent
class MyComponent {
showDetails = false;
toggleDetails() {
this.showDetails = !this.showDetails;
// Re-renderuj fragment z showDetails
const appRoot = document.querySelector('app-root') as any;
const templateFragment = appRoot.templateFragment;
const markers = templateFragment.getFragmentMarkers();
const detailsIndex = markers.findIndex(m =>
m.condition?.includes('showDetails')
);
if (detailsIndex >= 0) {
templateFragment.rerenderFragment(detailsIndex);
}
}
}
Przykład 2: Conditional rendering
<!-- Template -->
<ng-container *ngIf="isLoggedIn">
<div>Witaj, {{ userName }}!</div>
</ng-container>
<ng-container *ngIf="!isLoggedIn">
<button (click)="login()">Zaloguj się</button>
</ng-container>
// Po zalogowaniu
login() {
this.isLoggedIn = true;
this.userName = 'Jan Kowalski';
// Re-renderuj wszystkie fragmenty
const appRoot = document.querySelector('app-root') as any;
appRoot.templateFragment.rerenderAllFragments();
}
Przykład 3: Debugowanie w DevTools
// W konsoli przeglądarki
const appRoot = document.querySelector('app-root');
const markers = appRoot.templateFragment.getFragmentMarkers();
console.table(markers.map((m, i) => ({
index: i,
condition: m.condition || 'none',
hasContent: m.originalTemplate.length > 0
})));
// Re-renderuj konkretny fragment
appRoot.templateFragment.rerenderFragment(2);
Inspekcja w DevTools
W DevTools możesz zobaczyć markery jako komentarze:
<app-root>
<div>app</div>
<!--ng-container-start *ngIf="false"-->
<!--ng-container-end-->
<!--ng-container-start *ngIf="true"-->
<div>Widoczna zawartość</div>
<!--ng-container-end-->
</app-root>
Wydajność
- Re-renderowanie fragmentu jest szybsze niż re-renderowanie całego komponentu
- Markery w DOM zajmują minimalną ilość pamięci (tylko komentarze)
- Property bindings są przetwarzane tylko dla re-renderowanego fragmentu
Ograniczenia
- Markery są dodawane tylko dla
ng-containerz*ngIf - Zagnieżdżone
ng-containermają osobne pary markerów - Zmiana warunku wymaga ręcznego wywołania
rerenderFragment()
Przyszłe rozszerzenia
Planowane funkcjonalności:
- Automatyczne re-renderowanie przy zmianie właściwości
- Obsługa
*ngForw fragmentach - Animacje przy re-renderowaniu
- Lazy loading fragmentów