שימוש בפונקציית *ngFor trackBy
פורסם בתאריך 17 בנובמבר 2023
הבנת פונקציית *ngFor
trackBy
היא חשובה לשיפור ביצועי הלולאות שלך ושל האפליקציה שלך בכלל.
מה זה *ngFor
trackBy?
בקצרה, *ngFor
trackBy היא פונקציה שאתה יכול להעביר ללולאת *ngFor
שלך כדי לספר לאנגולר איך לעקוב אחר הפריטים ברשימה שלך. באופן ברירת מחדל, אנגולר מעקב אחר הפריטים ברשימה שלך לפי זהותם, כלומר ===
.
ברירת המחדל של trackBy
בואו נבין איך ה-trackBy
ברירת המחדל עובד.
נתחיל באפליקציה חדשה של Angular:
נשנה את app.component.ts
כך:
בדוגמא זו יש לנו רשימת פריטי משימות. אנו משתמשים ב-*ngFor
כדי לעבור על הפריטים ולהציג קלט עבור כל פריט. יש לנו גם כפתור שמוסיף פריט חדש לרשימה.
נשים input
בכל פריט כדי לוודא אם הרכיבים ברשימה נוצרים מחדש מאפס או שהרשימה משתנה ורכיב נוסף נוסף לרשימה.
ניתן להקליד משהו בקלט, אם הרשימה נוצרת מחדש תאבד את מצב הרכיב ב-DOM (מאחר שהוא נמחק), אבל במקרה זה אנו רואים שאנגולר מצליח לשמור על הרכיבים ב-DOM ורק להוסיף רכיב בסופו של הרשימה.
אנגולר יעבור על כל פריט ברשימה וישווה אותו לפריט הקודם ברשימה באמצעות ===
מאחר שהפריטים ברשימה הם אותם פריטים, כך גם הרכיבים ב-*ngFor
.
הבעיה
כל עוד הפריטים ברשימה נשארים אותם אין בעיה, הבעיה תתחיל כאשר הפריטים ברשימה ישתנו, מה שקורה לעיתים תכופות במקרה השימושי של *ngFor
כאשר אנו עוברים על רשימת פריטים שנלקחים מהשרת.
נדמיין את המקרה הבא, הרשימה נלקחת מהשרת, ויש לנו קלט חיפוש שישלח בקשת חיפוש לשרת ויציג לנו רשימה חדשה.
במקרה זה הפריטים ברשימה ישתנו, ואנגולר יחדיר את הרכיבים ברשימה מחדש, כלומר ישמיד את הרכיבים ב-DOM ויצור אותם מחדש מאפס.
ננסה לפשט את הדוגמא עם הקוד הבא:
נשים לב שבכל הוספה אנו בעצם מחדשים את הרשימה לחלוטין, אנו משתמשים בפונקציית clone
כדי לשכפל את הרשימה ולהוסיף פריט חדש לרשימה.
במקרה הבא נראה שהקלט ברכיב נמחק ונוצר מחדש מאפס, וכך גם הרכיב ב-DOM.
מעבר לאבדן המצב, זה גם בעיה ביצועים, מאחר שאנגולר ישמיד את כל רכיבי ה-DOM ברשימה ויצור אותם מחדש מאפס.
הפתרון
הפתרון הוא להשתמש בפונקציית *ngFor
trackBy, שתחליף את השוואת הברירת מחדל ===
עם פונקציית שוואה מותאמת.
ננסה להקליד משהו בקלט ולהוסיף פריט חדש לרשימה, נראה שהקלט נשמר ורק נוסף פריט לרשימה.
אכיפה באמצעות lint
היות וזה כל כך נפוץ ש-*ngFor
יקבל רשימה חדשה, יש מקומות שמאכפים את השימוש בפונקציית *ngFor
trackBy, על ידי הפעלת כלל ב-lint של @angular-eslint
.
נעדכן את הקובץ .eslintrc
:
נשים לב שהוספנו את "parser": "@angular-eslint/template-parser",
ואת הכלל: "@angular-eslint/template/use-track-by-function": "error"
.
כעת כאשר אתם מריצים npx ng lint
בלי הפונקציית trackBy
תקבלו שגיאת lint.
נמליץ על הוספת חוק ה lint כדי להבטיח שהפונקציית trackBy
תשמש בכל מקום שבו יש שימוש ב-*ngFor
.
סיכום
כאשר אתם משתמשים ב-*ngFor
תשאלו את עצמכם את השאלות הבאות:
- אילו רכיבים ברשימה נוצרים מחדש, ואיך אני יכול לבצע אופטימיזציה כך שרק הרכיבים הנדרשים ברשימה יעודכנו, ולא כל הרשימה.