כדי לשפר את הרספונסיביות של רשימות גדולות, כדאי להטמיע גלילה וירטואלית.
רשימה נגללת היא אחד מדפוסי ממשק המשתמש הנפוצים ביותר כיום, בין אם אתם גולשים בפיד עם גלילה מתמשכת באתר המדיה החברתית האהוב עליכם, או מנווטים במרכז בקרה ארגוני. כשרשימות הגלילה ארוכות מאוד (מאות, אלפי או מאות אלפי פריטים), ביצועי האפליקציה עלולים להיפגע.
רשימות גדולות עלולות להיטען לאט כי האפליקציה צריכה לטעון ולעבד את כל הנתונים מראש. בנוסף, יכול להיות שייקח זמן לעבד אותן ולנווט בהן, כי כל פריט ברשימה יכול להכיל מידע מגוון, מדיה ופונקציונליות.
המשתמשים עלולים להיתקל בבעיות כשהם טוענים את הדף או גוללים בו, מה שעלול לגרום לתסכול ולעזיבת הדף.
גלילה וירטואלית ב-Angular באמצעות ערכת הפיתוח של הרכיבים (CDK)
גלילה וירטואלית היא השיטה העיקרית שמשמשת לטיפול בבעיות האלה. גלילה וירטואלית נותנת רושם של רשימה גדולה מאוד, על ידי מתן סרגל גלילה בגודל מתאים, והיכולת לנווט ברשימה מבלי לדרוש מהאפליקציה להחזיק את כל הרשימה בזיכרון או לעבד אותה בדף.
ב-Angular, הגלילה הווירטואלית מסופקת על ידי Component Dev Kit (CDK). אם תשנו את האופן שבו אתם עוברים על רשימות ותספקו כמה פרמטרים נוספים של הגדרה, הגלילה הווירטואלית של ה-CDK תנהל באופן אוטומטי את הרינדור הווירטואלי של הרשימות, ותשפר את הביצועים ואת מהירות התגובה של הדף.
במקום לעבד את כל הרשימה בבת אחת, רק קבוצת משנה של הפריטים שמתאימה למסך (בתוספת מאגר קטן) תעובד. כשהמשתמש מנווט, קבוצת משנה חדשה של פריטים מחושבת ומעובדת, תוך שימוש חוזר ב-DOM הקיים אם רוצים.
בהמשך הפוסט הזה נסביר איך להגדיר גלילה וירטואלית בסיסית. באפליקציה לדוגמה הזו אפשר לראות דוגמה מלאה:
הגדרת גלילה וירטואלית
קודם כל, ודאו שהתקנתם את @angular/cdk באמצעות מנהל החבילות המועדף עליכם. כדי להתקין אותו באמצעות npm, מריצים את הפקודה הזו בטרמינל:
npm install --save @angular/cdk
הוספת ScrollingModule לאפליקציה
אחרי שמתקינים את ה-CDK, מייבאים את ScrollingModule, שמטפל בגלילה וירטואלית, מהחבילה @angular/cdk/scrolling. ואז מוסיפים אותו למערך הייבוא של המודול:
import {ScrollingModule} from '@angular/cdk/scrolling';
...
imports: [
ScrollingModule
...
]
...
יצירת אזור תצוגה
כדי לראות איך החבילה פועלת, נסו ליצור רכיב עם רשימת מספרים מ-0 עד 99,999:
@Component({
template: `<div *ngFor="let item of list">{{item}}</div>`
})
export class ScrollComponent {
list = Array.from({length: 100000}).map((_, i) => i);
}
כשהדפדפן מעבד את האפליקציה, הוא צריך לעבד 100,000 רכיבי <div> נפרדים. זה יכול להתאים לצומתי טקסט בסיסיים, אבל כל מורכבות בתבנית שחוזרת על עצמה לא מתאימה לשינוי קנה מידה, וכל רכיבי ה-event listener יוכפלו באופן משמעותי.
כדי להוסיף גלילה וירטואלית ולמנוע את הבעיות האלה, צריך ליצור אזור תצוגה על ידי הוספת הרשימה לאלמנט <cdk-virtual-scroll-viewport>:
@Component({
template: `<cdk-virtual-scroll-viewport>
<div *ngFor="let item of list">{{item}}</div>
</cdk-virtual-scroll-viewport>`
})
export class ScrollComponent {
list = Array.from({length: 100000}).map((_, i) => i);
}
מכיוון ש-ScrollingModule מעבד באופן דינמי קבוצות משנה של הרשימה, צריך לציין את גובה אזור התצוגה באמצעות CSS רגיל. צריך גם לתת ל-viewport רמז לגבי התוכן שלו על ידי ציון ה-itemSize. המודול משתמש במידע הזה כדי לקבוע כמה פריטים לשמור ב-DOM בכל זמן נתון ואיך לעבד סרגל גלילה בגודל מתאים.
@Component({
template: `<cdk-virtual-scroll-viewport itemSize="18" style="height:80vh">
<div *ngFor="let item of list">{{item}}</div>
</cdk-virtual-scroll-viewport>`
})
export class ScrollComponent {
list = Array.from({length: 100000}).map((_, i) => i);
}
לבסוף, ממירים את *ngFor ל-*cdkVirtualFor:
@Component({
template: `<cdk-virtual-scroll-viewport itemSize="18" style="height:80vh">
<div *cdkVirtualFor="let item of list">{{item}}</div>
</cdk-virtual-scroll-viewport>`
})
export class ScrollComponent {
list = Array.from({length: 100000}).map((_, i) => i);
}
במקום לעבור על כל הרשימה, אזור התצוגה מזהה באופן דינמי את קבוצת המשנה הנכונה של הרשימה ועובר עליה. עכשיו, כשהמשתמש טוען את הדף, ה-CDK אמור להציג את קבוצת המשנה של הרשימה שמתאימה למסך (בתוספת מאגר נתונים זמני קטן), וכל אירועי הגלילה באזור התצוגה טוענים ומציגים את קבוצת המשנה המתאימה של הרשימה:
השלבים הבאים
יכולות הגלילה הווירטואלית של ה-CDK הן הרבה יותר רחבות מהדוגמה הבסיסית הזו. באפליקציה לדוגמה, כל הרשימה הייתה בזיכרון, אבל באפליקציות מורכבות יותר אפשר לאחזר את הרשימה לפי דרישה. כדי לקבל מידע נוסף על היכולות האחרות של ScrollingModule ועל ההוראה cdkVirtualOf, קראו על Scrolling במאמרי העזרה של CDK.