What is infinite scroll in angular?

Behersk Rulning i Angular: Fra Uendelig til Virtuel

15/02/2025

Rating: 4.56 (1121 votes)

I den moderne app-udvikling er en flydende og responsiv brugeroplevelse afgørende. En af de mest effektive måder at opnå dette på, især med store mængder indhold, er gennem intelligente rullefunktioner. Fra den intuitive uendelige rulning, der holder brugerne engagerede, til avanceret kontrol over elementers synlighed og optimering med virtuel rulning – Angular tilbyder robuste værktøjer til at håndtere alle disse scenarier. Denne artikel vil guide dig gennem de forskellige aspekter af rullefunktionalitet i Angular, give dig praktisk indsigt og hjælpe dig med at vælge den bedste løsning til dine specifikke behov.

What is infinite scroll in angular?
Infinite scrolling is a popular pattern that loads content continuously as users scroll, instead of using traditional pagination.Apps like Instagram, Twitter, or even Google Images using infinite scrolling apporch instead of pagination. In this blog, we’ll cover three ways to implement infinite scroll in Angular: 1. Using ngx-infinite-scroll

Lad os udforske, hvordan du kan forbedre din Angular-app med kraftfulde rullemetoder, der både optimerer ydeevnen og forbedrer brugeroplevelsen markant.

Indholdsfortegnelse

Hvad er Uendelig Rulning (Infinite Scrolling)?

Uendelig rulning er et populært brugergrænseflademønster, hvor indholdet kontinuerligt indlæses, efterhånden som brugeren ruller nedad, i stedet for at bruge traditionel paginering (sidenummerering). Tænk på apps som Instagram, Twitter eller selv Google Images – de bruger alle denne tilgang til at holde indholdet flydende og uafbrudt. Denne metode skaber en sømløs browsing-oplevelse, hvor brugeren sjældent behøver at klikke for at se mere indhold. Det er især effektivt for indholdsfeeds, nyhedsstrømme og billedgallerier, hvor mængden af data kan være enorm.

Fordelene ved uendelig rulning er mange. For det første forbedrer det brugerengagementet ved at fjerne friktionen ved at skulle klikke på 'næste side'. Brugerne kan simpelthen fortsætte med at rulle og opdage nyt indhold. For det andet kan det forenkle datahåndteringen på serversiden, da data kan sendes i mindre, mere håndterbare klumper, efterhånden som de efterspørges. Dog er det vigtigt at overveje potentielle ulemper, såsom vanskeligheder med at finde specifikt indhold igen eller mangel på en 'bund' på siden, hvilket kan føles desorienterende for nogle brugere. I Angular kan uendelig rulning implementeres ved at lytte til rullebegivenheder på vinduet eller et specifikt rullebart element og derefter udløse en datahentning, når brugeren nærmer sig bunden af det eksisterende indhold.

Automatisk Rulning og Elementkontrol

Udover den kontinuerlige indlæsning af indhold er der mange scenarier, hvor du ønsker at have mere præcis kontrol over rulningen i din Angular-app. Dette kan omfatte alt fra at registrere, når en bruger når toppen eller bunden af et element, til programmatisk at rulle til en specifik position eller et bestemt element på siden. Lad os dykke ned i nogle af disse avancerede teknikker.

Registrering af Rullegrænser og Procent

Forestil dig et stort tekstområde (<textarea>), hvor du ønsker at give feedback, når brugeren når toppen eller bunden, eller endda vise, hvor langt de har rullet. Dette kan opnås ved at lytte til rullebegivenheder og udnytte elementets rulleegenskaber:

  • scrollHeight: Den samlede højde af elementets indhold, inklusive ikke-synligt indhold.
  • clientHeight: Den synlige højde af elementet (uden rullepaneler).
  • scrollTop: Antallet af pixels, elementet er rullet fra toppen.

Ved at kombinere disse egenskaber kan vi bestemme, om brugeren har nået toppen eller bunden, og endda beregne rulleprocenten. For eksempel, hvis this.box?.nativeElement.scrollHeight === (this.box?.nativeElement.scrollTop + this.box?.nativeElement.clientHeight), har brugeren nået bunden af tekstområdet. Hvis this.box?.nativeElement.scrollTop === 0, er de ved toppen. Rulleprocenten kan beregnes som (this.box?.nativeElement.scrollTop / totalHeightToBeScrolled) * 100.

Udvidelse af Elementer for Fuld Synlighed

Nogle gange ønsker du at give brugeren mulighed for at udvide et element, så alt dets indhold bliver synligt uden rullepaneler. Dette er særligt nyttigt for tekstområder eller informationsbokse, der indeholder mere tekst, end der oprindeligt vises. I Angular kan du opnå dette ved at indstille elementets højde til dets scrollHeight. Ved at bruge Angulars Renderer2 kan du sikkert manipulere DOM'en og dynamisk justere elementets stil:

expand() {
this.renderer.setStyle(this.box?.nativeElement, 'height', `${this.box?.nativeElement.scrollHeight}px`);
}

Denne metode sikrer, at hele indholdet er synligt, og at rullepanelerne forsvinder, hvilket giver en renere visning.

How to use viewportscroller in angular?
So, I tried another way, using Angular's ViewportScroller. In order to do that, you have to inject ViewportScroller at Component's constructor, like constructor(private scroller: ViewportScroller) and just call this.scroller.scrollToAnchor("");.

Programmatisk Rulning i Dokumentet

Udover manuel rulning kan du også programmatisk rulle til bestemte positioner på siden. Dette er nyttigt for 'Tilbage til top'-knapper, navigationslinks eller for at guide brugeren til et bestemt afsnit.

  • Rulning til Top/Bund af Dokumentet: Brug window.scrollTo() metoden. Du kan angive top (Y-akse), left (X-akse) og behavior ('smooth' for en flydende animation eller 'instant' for øjeblikkelig rulning).
    scrollToTop() {
    window.scrollTo({ top: 0, left: 0, behavior: 'smooth' });
    }

    scrollToBottom() {
    let fullDocumentHeight = Math.max(
    document.body.scrollHeight, document.documentElement.scrollHeight,
    document.body.offsetHeight, document.documentElement.offsetHeight,
    document.body.clientHeight, document.documentElement.clientHeight
    );
    window.scrollTo({ top: fullDocumentHeight, left: 0, behavior: 'smooth' });
    }
  • Rulning til Specifikke Elementer: Hvis du vil rulle til et bestemt element inden for din komponent, er scrollIntoView() metoden på selve elementet ideel. Dette kræver, at elementet har et ID. Du kan finde elementet med document.querySelector() og derefter kalde scrollIntoView().
    scrollToSpecific() {
    document.querySelector(`#box${this.elementTarget}`)?.scrollIntoView({
    behavior: 'smooth',
    block: 'start', // 'start', 'center', 'end', 'nearest'
    inline: 'nearest' // 'start', 'center', 'end', 'nearest'
    });
    }

    block-egenskaben bestemmer den vertikale justering (f.eks. om toppen af elementet skal justeres med toppen af den synlige område, eller om bunden skal justeres med bunden). inline-egenskaben gør det samme for den horisontale justering.

Forståelse af Intersection Observer API

En af de mest kraftfulde og moderne måder at detektere synligheden af et element på skærmen er ved at bruge Intersection Observer API. Dette API løser problemet med at skulle lytte til rullebegivenheder og manuelt beregne elementets position, hvilket kan være ydeevnekrævende. I stedet giver Intersection Observer en mere effektiv måde at observere ændringer i skæringspunktet mellem et mål-element og dets rod-element (typisk viewporten).

API'et er ideelt til use cases som lazy loading af billeder eller komponenter, annoncesynlighedssporing, eller når du vil udløse en animation, når et element kommer ind i syne. Konceptet er relativt simpelt: du opretter en observer, specificerer et rod-element (hvis ikke viewporten), en margin omkring roden og en række tærskelværdier (threshold). Observeren vil derefter kalde en callback-funktion, når mål-elementets synlighed krydser en af disse tærskelværdier.

Sådan Opsætter du Intersection Observer i Angular

Typisk implementeres dette i en Angular-direktiv for genanvendelighed. Direktivet vil indeholde logikken for at oprette og observere elementet.

Først definerer du IntersectionObserver-indstillingerne:

public intersectionOptions = {
root: null, // Betyder, at roden er dokumentets viewport
rootMargin: "0px",
threshold: [0, 0.5, 1] // Udløser callback, når 0%, 50% eller 100% af elementet er synligt
};

root: null angiver, at viewporten er roden. rootMargin tilføjer en margin omkring rod-elementet, og threshold definerer, hvornår callback-funktionen skal udløses baseret på procentdelen af mål-elementets synlighed i roden.

Derefter opretter du observeren i en lifecycle hook som ngAfterViewInit:

ngAfterViewInit() {
let observer = new IntersectionObserver(
this.intersectionCallback.bind(this),
this.intersectionOptions
);
if (this.isTargetElement) { // Observerer kun, hvis dette er mål-elementet
observer.observe(this.element.nativeElement);
}
}

observer.observe(this.element.nativeElement) fortæller observeren, hvilket specifikt DOM-element den skal holde øje med.

How do I enable virtual scrolling?
To enable virtual scrolling over these type of elements, place the elements in their proper parent, and then wrap the whole thing in a cdk-virtual-scroll-viewport. Be careful that the parent does not introduce additional space (e.g. via margin or padding) as it will interfere with the scrolling.

Endelig håndterer du callback-funktionen, som kaldes, når en af tærskelværdierne krydses:

intersectionCallback(entries: IntersectionObserverEntry[], observer: IntersectionObserver) {
entries.forEach((entry) => {
if (entry.intersectionRatio === 1) {
this.elementVisible.emit(true); // Element er fuldt synligt i viewport
} else {
this.elementVisible.emit(false);
}
});
}

entry.intersectionRatio er et tal mellem 0 og 1, der angiver, hvor stor en del af mål-elementet der er synligt. Når det er 1, er elementet fuldt synligt, og du kan udløse den ønskede handling, f.eks. en alert-dialog eller en datahentning.

Vælg den Rigtige Rullemetode i Angular

Når det kommer til at rulle til en specifik anker (et element med et ID) i Angular, er der flere veje at gå, men ikke alle er lige pålidelige, især i produktionsmiljøer. Det er vigtigt at forstå forskellene og vælge den mest robuste metode.

Sammenligning af Rullemetoder til Ankre:

1. DOM-kommandoer (Element.scrollIntoView() eller document.getElementById().scrollIntoView()):

  • Fordele: Simpel, direkte adgang til DOM. Fungerer ofte fint i udviklingsmiljøer.
  • Ulemper: Kan være upålidelig i Angular-applikationer, især i produktionsmiljøer eller når Angular Material bruges, da Angulars rendering og 'zone.js' kan forstyrre direkte DOM-manipulation på uventede måder.

2. Angulars ViewportScroller:

  • Fordele: Angular-specifik service, type-sikker. Involverer injektion af ViewportScroller i din komponent. Kaldes med this.scroller.scrollToAnchor("<yourTarget>");.
  • Ulemper: Ligesom direkte DOM-manipulation kan denne metode også fejle i produktionsmiljøer af årsager, der ikke altid er umiddelbart indlysende, potentielt på grund af Angulars interne håndtering af rullebegivenheder eller tredjepartsbiblioteker.

3. Angulars Router med fragment:

  • Fordele:Mest pålidelige metode i Angular-applikationer, især i produktion. Udnytter Angulars router til at navigere til et anker, hvilket sikrer, at Angulars interne mekanismer håndterer rulningen korrekt. Involverer injektion af Router og brug af this.router.navigate([], { fragment: "<yourTarget>" });.
  • Ulemper: Kræver, at din applikation bruger Angular Router.

Anbefaling:

Baseret på erfaringer, hvor de to første metoder har fejlet i produktionsmiljøer, er den anbefalede tilgang at bruge Angulars Router med fragment til at rulle til specifikke ankre. Dette sikrer den mest konsistente og pålidelige adfærd på tværs af forskellige miljøer og konfigurationer af din Angular-applikation.

MetodeFordeleUlemperAnbefaling
DOM-kommandoer (scrollIntoView)Enkel, direkte adgang til DOMKan fejle i Angular-apps (produktionsmiljø)Undgå i Angular-apps for pålidelighed
Angulars ViewportScrollerAngular-specifik, type-sikkerKan fejle i produktionsmiljøUndgå i Angular-apps for pålidelighed
Angulars Router med fragmentMest pålidelig i Angular-appsKræver Angular Router-modulAnbefales stærkt

Virtuel Rulning: Optimer Ydeevnen

Når du arbejder med ekstremt lange lister af data, kan selv uendelig rulning begynde at lide under ydeevneproblemer, da DOM'en bliver overbelastet med tusindvis af elementer. Her kommer virtuel rulning ind i billedet som en kraftfuld optimeringsteknik. Virtuel rulning gengiver kun de elementer, der aktuelt er synlige i viewporten, samt et lille antal elementer lige uden for syne (for at give en flydende overgang). Elementer, der er langt væk fra den synlige område, fjernes fra DOM'en og genoprettes kun, når de nærmer sig syne.

Dette reducerer markant antallet af DOM-elementer, som browseren skal håndtere, hvilket fører til en betydelig forbedring af ydeevnen, især på enheder med begrænsede ressourcer. Angular Material CDK (Component Dev Kit) leverer en modul til virtuel rulning via cdk-virtual-scroll-viewport.

Sådan Aktiveres Virtuel Rulning

For at aktivere virtuel rulning skal du placere dine lister af elementer inde i en cdk-virtual-scroll-viewport-komponent. Det er afgørende, at forældre-elementerne omkring cdk-virtual-scroll-viewport ikke introducerer yderligere plads (f.eks. via margin eller padding), da dette kan forstyrre rulningen og elementernes korrekte placering.

What is auto scrolling?
Auto scrolling to a specific element or position in the page. Instead of a manual scroll, I want to easily scroll to the top/bottom of the document via a button click. I have added the below button at the bottom of the document. I have added another button at the top of the document.
<cdk-virtual-scroll-viewport itemSize="50" class="my-viewport">
<div *cdkVirtualFor="let item of items" class="list-item">
{{item.name}}
</div>
</cdk-virtual-scroll-viewport>

itemSize-attributten er vigtig, da den fortæller viewporten den forventede højde af hvert element, hvilket muliggør korrekt beregning af rullepositioner. Virtuel rulning er en fremragende løsning for situationer, hvor du har brug for at vise meget lange lister uden at gå på kompromis med ydeevnen.

Ofte Stillede Spørgsmål (FAQ)

Hvad er forskellen på scrollTop og scrollY?

scrollTop bruges til at bestemme antallet af pixels rullet fra toppen af et element (f.eks. et <div> eller <textarea>). scrollY (eller window.scrollY) bruges til at bestemme antallet af pixels rullet fra toppen af dokumentet (vinduet). De opererer på forskellige niveauer af DOM-træet.

Hvorfor fungerer mine rullekommandoer ikke i produktion?

Dette er et almindeligt problem i Angular-applikationer. Ofte skyldes det, at Angular Material eller andre biblioteker ændrer DOM'en eller fanger rullebegivenheder på en måde, der forhindrer direkte DOM-manipulation eller ViewportScroller i at fungere korrekt. Som diskuteret, er den mest pålidelige løsning at bruge Angular Router med fragment til at rulle til ankre, da dette er designet til at fungere inden for Angulars økosystem.

Hvornår skal jeg bruge Intersection Observer?

Intersection Observer API er ideel til scenarier, hvor du skal detektere, når et element bliver synligt i viewporten eller krydser en bestemt synlighedstærskel. Typiske anvendelser inkluderer:

  • Lazy loading: Indlæs billeder eller komponenter kun når de kommer ind i syne.
  • Annonce-synlighed: Spor, om en annonce rent faktisk er blevet set af brugeren.
  • Analytics: Registrer, når brugere ser bestemte dele af din side.
  • Scroll-baserede animationer: Start animationer, når et element kommer ind i syne.

Kan virtuel rulning erstatte uendelig rulning?

Nej, de er komplementære snarere end erstatninger. Uendelig rulning handler om hvornår du henter mere data (når brugeren ruller nær bunden). Virtuel rulning handler om hvordan du gengiver data (kun de synlige dele) for at optimere ydeevnen for meget lange lister. Du kan med fordel kombinere begge teknikker: brug uendelig rulning til at hente data i klumper, og brug virtuel rulning til effektivt at vise den store mængde data, du har hentet.

Er uendelig rulning altid den bedste løsning?

Ikke altid. Mens uendelig rulning er fremragende for feeds og gallerier, kan det være problematisk for indhold, hvor brugere ofte ønsker at springe til bestemte sider eller referere tilbage til tidligere indhold (f.eks. produktsøgninger med mange filtre eller teknisk dokumentation). I sådanne tilfælde kan traditionel paginering give en bedre brugeroplevelse ved at tilbyde mere kontrol og kontekst om den aktuelle placering i indholdet.

Konklusion

Rullefunktionalitet er en fundamental del af enhver moderne webapplikation, og Angular tilbyder et rigt sæt værktøjer til at håndtere selv de mest komplekse scenarier. Fra at levere en flydende brugeroplevelse med uendelig rulning til at optimere ydeevnen for store datasæt med virtuel rulning, har du nu en dybere forståelse af de tilgængelige teknikker.

Husk, at valget af rullemetode afhænger af din applikations specifikke behov og den type indhold, du præsenterer. Ved at anvende de rigtige teknikker – hvad enten det er præcis elementkontrol, den intelligente Intersection Observer API eller den robuste Router-baserede rulning til ankre – kan du skabe en Angular-applikation, der ikke kun er visuelt tiltalende, men også yderst responsiv og brugervenlig. Gå i gang med at implementere disse strategier, og tag din Angular-apps brugeroplevelse til det næste niveau!

Hvis du vil læse andre artikler, der ligner Behersk Rulning i Angular: Fra Uendelig til Virtuel, kan du besøge kategorien Mobil.

Go up