כמתכנת אנגולר אני מאמין שלא פעם יצא לך לחשוב איך אנגולר מזהה שינויים בנתונים מרנדר מחדש את ה- view.
זה נקרא Change Detection Strategy. במדריך הזה נסקור את המנגנון הזה של אנגולר ונלמד איך להשתמש בו.
אז מה זה בעצם Change Detection ?
הטכניקת של הזהוי שינויים בעצם משווה בין 2 סטייטים - הנוכחי והחדש אם יש שינוי ביניהם זה אומר שהדף צריך להתרנדר.
אז מה בעצם קורה ? המתכנת עשה שינוי בקומפוננטה ואנגולר מרנדר מחדש את העמוד.
נשמע דיי פשוט וטריוויאלי אבל מה שקורה מאחורי הקלעים זה שאנגולר מחפש את כל הקבצים, מבצע מחדש את כל הביטויים, משווה אותם לערכים הקודמים ומפיץ את השינוי לרכיבי ה-DOM אם מזוהה שינוי.
וככל שהאפליקציה שלנו גדלה אז בדיקה כזאת לוקחת יותר זמן.
אם נסתכל על עץ הקומפוננטות הבא:
ובכל פעם שהמתכנת יעשה שינוי בקומפוננטה ForgotPasswordComponent מנגנון change detection יופעל בצורה הבאה:
- המנגנון יעבור על כל קומפוננטה בעץ ויבדוק אם יש שינוי בה (הבדיקה מתחילה מלמעלה ללמטה)
- אם אנגולר ימצא שינוי באחת הקומפוננטות הוא יבצע את השיוני ויעשה רנדור מחדש.
לאנגולר יש 2 אסטרטגיות ל- change detection
- Default
- onPush
Defualt:
זה בעצם מה שהסברתי בפסקה הקודם שכל שינוי גורר אחריו בדיקה של כל הקומפננטות מלמעלה למטה.
אז כבר הבנו שסוג כזה של התנהגות יכול להשפיע על כל הביצועים של המערכת שלנו.
OnPush:
אנחנו משנים את הסטרטגיית של Change Detection ע"י הוספת ChangeDetectionStrategy.OnPush ל- changeDetection ב- @Component.
עם ההסטרטגיית OnPush אנחנו בעצם מדלגים על קומפוננטות שממשות onPush ועל כל הילדים שלה.
אנגולר יעדכן את הקומפוננטה רק במקרים הבאים:
- ה- @Input ישתנה רק במקרה שיש הפניה חדשה
- קרה event בקומפוממטה או באחד מהילדים שלה
- אם async pipe מקבל ערך חדש
- הפעלה מנגנון הזיהוי באופן ידני
נרחיב על כל אחד מהמקרים:
@input
אנגולר יריץ change detector במקרה של שינוי בהפניה. ז"א אם נרצה להעביר אובייקט נצטרך לשנות אותו ע"י יצירת אובייקט חדש.
Event Handler
כל אירוע שקורה בקומפוננטה או בילדים של הקומפוננטה יפעיל את כל עץ הקומפוננטות של האפליקציה.
אירועים שלא יופעלו כאשר נשתמש ב onPush:
* promise
* setTimout
* setInterval
* RxJS observable subscription
Async Pipe
אנגולר מריץ אוטומטית את markForCheck בכל פעם שאנחנו מפעילים את ה- aync pipe
הפעלת מנגנון הזיהוי באופן ידני:
אז אנחנו יכולים לפהעיל את זה ע"י שימוש:
- detectChanges() - ירץ את ה- change detection על הקומפוננטה ועל כל הילדים שלה
- ApplicationRef.tick() - ירץ את ה- change detection על כל עץ הקומפוננטות שזה בעצם על כל הפרויקט.
- markForCheck() - אינו גורם לזיהוי שינוי, אלא מסמן את כל אבות onPush כפי שנבדקו פעם אחת, או כחלק מהמחזור הנוכחי או השינוי הבא.
לסיכום
אנגולר Change Detection הוא מנגנון מאוד חשוב.
הוא מספק לנו ביצועים טובים יותר לאפליקציה שלנו בגלל שאנגולר לא צריך לבדוק בכל שינוי את כל הקומפוננטות