איי שם בשנת 2013, פרסמתי פוסט בשם "שלום, אנגולר!", בתקופה בה אנגולר היה דבר חדש ולא כ"כ מוכר.
הפוסט זכה לאלפי ציפיות ולא מעט תגובות, אחת מהן נוספה רק בשנת 2017:
אנגולר 2 נכתבה מחדש (נרחיב מיד) - ועוררה מהומה גדולה. על גרסה 3 דילגו - וקפצו ישר לגרסה 4. כיום הגרסה הנוכחית היא גרסה 8, וכל חצי שנה צפויה לצאת גרסה חדשה.
את המהומה הגדולה שהייתה בעת הצגת אנגולר 2.0 - כבר פספסנו, העניינים נרגעו מאז. אתייחס אליהם בקצרה.
אנגולר, למרות שנכתבה מחדש - היא עדיין ספריה פופולרית למדי (קצת פחות מ React ו Vue - הרזות והפשוטות יותר ללמידה), היא עדיין מכוונת לפיתוח אפליקציות SPA (קרי: Single Page Application) מורכבות, היא עדיין דעתנית לגבי איך יש לכתוב אפליקציות ווב, והיא עדיין מספקת פתרון פיתוח שלם.
למה דווקא עכשיו?
לא רק בגלל דני, והתגובה שלו (אני מאחר בתגובות באופן כללי, אבל שנתיים זה באמת מוגזם) - אלא בגלל שהנושא רלוונטי ב Next-Insurance - המקום בו אני עובד. יש לנו כמה אפליקציות SPA מורכבות - הכתובות באנגולר.
אם אתם רוצים להבין מה היתרונות והחסרונות של אנגולר מול React ו Vue המאוד פופולריות - חפשו במקום אחר. זה לא יהיה חלק מהפוסט. יש המון חומר באינטרנט. בפוסט אנסה לתת סקירה מהירה על אנגולר 2 (או 8, בעצם) כך שאחרי רבע שעה קריאה - תרגישו שאתם מכירים את הספרייה אולי כבר שבוע.
הווב מפוצץ בחומר על ספריות צד-לקוח, וגם על אנגולר, אך באמת לא הצלחתי למצוא בזמן סביר, סקירה שהשביעה את דעתי. זה הסימן עבורי: לכתוב סקירה כזו בעצמי.
פתרון מקיף - כבר אמרנו? |
מהי אפליקציית אנגולר?
אפליקציית אנגולר היא סט של Components ו Services מאורגנים לתוך מודולים של אנגולר:
- Components הם רכיבים ויזואליים, שרואים על המסך.
- Services הם שירותים לוגיים המשרתים את ה Components. שירותים בסיסיים המשותפים לכל האפליקציה - יושיבם במודול הראשי שנקרא ה "App Module".
שימו לב שיש הבדל בין Angular Module לבין ES6 Module. בדומה ל ES6 modules גם Angular Modules מאגדים קוד בעל מאפיינים דומים - אך יש להם סמנטיקות נוספות. לאורך הפוסט כאשר אתייחס ל"מודולים" הכוונה היא ל Modules של אנגולר.
ה Components מאורגנים בהיררכיה, וכל אחד הוא View ("מסך") או חלק מהמסך:
מכיוון שאנגולר מרכיב לרוב Single Page Applications (קרי SPA), ה Root Component יהיה לרוב המסגרת לדף הסטנדרטי, וכל "תוכן אפשרי של מסך" יהיה Component נוסף - שגם הוא יורכב מ Sub-Components נוספים.
- הפרקטיקה היא ש Components מכילים כמות מוגבלת של קוד. אם Component הוא גדול ומורכב - הרי שיש לפרק אותו לכמה Components (בדומה ל microservices)
- Components הם reusable, ורבים מהם יופיעו שוב ושוב - במסכים שונים של האפליקציה.
- אפשר לחשוב על Component כתגית HTML חדשה עבור האפליקציה, למשל <customers-table> שאותה ניתן לשלב בכמה מסכים שונים. ייתכן וארצה ליצור רכיב בשם <customers-table-and-details> שמציג את הטבלה, וכמה שדות עם פרטים נוספים עבור הלקוח שנבחר. גם רכיב כזה יכול להיות שימושי בכמה מסכים שונים.
עד כמה קטנים נכון שיהיו הרכיבים (קרי: Components)? לרוב ברמה של כמה רכיבים ויזואליים מאוגדים יחדיו, אך לעתים יש טעם להגדיר Component מסביב לרכיב ויזואלי יחיד, למשל: כאשר נלווה לרכיב הזה לוגיקה השווה re-use.
מודולים
את כלל הקוד באפליקציה מחלקים למודולים, בד"כ ע"פ הקריטריונים הבאים:
- מסך מורכב או קבוצת מסכים המטפלים בנושא מסוים - הם מודול. לרוב נקרא: Feature Module. למשל: מסכי הגדרת לקוח - הם בסיס איתן למודול עצמאי.
- פיצ'ר לוגי במערכת - יכול להיות מודול. למשל Data Export, לא כולל הרבה UI (אולי רכיב בודד) אך כולל הרבה לוגיקה או עבודה עם מערכות חיצוניות - מצדיק מודול. ייתכן וניתן לעשות Data Export לדברים שונים ממסכים שונים במערכת. זה גם Feature Module - אך מסוג מעט אחר.
- Shared Modules הכוללים רכיבים ו/או שירותים שזקוקים להם בכמה חלקים של האפליקציה. לעתים Shared Modules הם משותפים בין כמה אפליקציות.
- הרבה פעמים מקובל ליצור באפליקציה מודול משותף בשם core - על מנת שה AppModule יישאר קטן ככל האפשר. ה AppModule מייבא אותו ומחצין (export) אותו לכל שאר המודולים באפליקציה.
כל מודול יכול להשתמש ברכיבים ו Services שלו, באלו של ה AppModule (הציבוריים), ובאלו (הציבוריים) של מודול שהוא מייבא (import).
מודולים יכולים להיטען בצורה דינמית, וזה שיקול נוסף בחלוקה למודולים: מודולים הם יחידת הטעינה הדינאמית של אנגולר. למשל: אם יש לי אפליקציה עם 100 "מסכים", אף בשימוש טיפוסי משתמש ייגש רק לכ 10 "מסכים" - חבל מאוד לטעון את כל הקוד בהתחלה. כאשר יש אפליקציה SPA גדולות (שזה בעצם ה use-case העיקרי של Angular) - טעינה נבונה של מודולים עשויה לשפר מאוד את הביצועים.
TypeScript או ג'אווהסקריפט?
קוד Angular יכול להיכתב ב ES5 (ג'אווהסקריפט גרסת 2009 - כתבתי כמה פוסטים על חידוש שפת הג'אווהסקריפט חלק א', חלק ב', חלק ג') או גרסאות מתקדמות יותר, אך מקובל לכתוב Angular בעזרת TypeScript - זו ההמלצה הרשמית + Angular בעצמה נכתבת ב TypeScript.
TypeScript היא שפה מודרנית ומתוכננת-היטב, בניגוד גמור ל JavaScript המקורית.
- שמה של השפה נובע ממערכת ה Types שלה, שמקל לבדוק את נכונות הקוד - אבל מאפשר גם ל IDEs לעבוד בצורה עמוקה יותר עם הקוד: מציאת שגיאות אפשריות, Refactoring ו Navigation ברמה ששפה דינמית וללא טיפוסים כמו JavaScript - לא מאפשרת.
- TypeScript היא SuperSet של שפת ג'אווהסקריפט, כלומר: ג'אווהסקריפט היא מקרה פרטי של TypeScript (בערך). לדוגמה: אם ניקח קובץ js. ונשה את שמו ל ts. לרוב נצטרך להוסיף הגדרה של טיפוסים - אך משם הוא יעבוד.
- הדפדפן לא מכיר TypeScript, ולכן הקוד מתורגם (Transpiled) לשפת ג'אווהסקריפט.
- אם תראו את קוד הג'אווהסקריפט שנוצר מ Typescript - הוא יהיה דומה מאוד לקוד ה Typescript שכתבתם.
- TypeScript מכילה את רוב היכולות של ES6 - אך לא את כולן. למשל: אין תמיכה ב Proxy (כלי דיי מתקדם, ולא לשימוש יומיומי). עם הזמן TypeScript מוסיפה עוד אלמנטים מ ES6, וגם אלמנטים ייחודיים משלה.
TypeScript, כפי שאמרנו, היא יישום של ES6 עם כמה תוספות, בעיקר:
- Static Typing - למשתנים יש טיפוסים, והקומפיילר (ליתר דיוק: טרנספיילר) בודק את נכונות השימוש בהם עוד לפני שהקוד רץ.
- Interfaces שלא קיימים בג'אווהסקריפט - הם תוספת משמעותית. למי שעבד בג'אווה - אין צורך להסביר את החשיבות.
- Class Properties - קיימים ב ES6, אך בצורה לא מפורשת. ב TypeScript ניתן להגדיר properties על מחלקה בצורה מפורשת (או בתחביר מקוצר בתוך ה constructor) - מה שמאוד נוח ושימושי.
- נראות - members במחלקה של TypeScript יכולים להיות גם private. ב ES6 נראות היא בעיקר ברמת המודולים.
מה ההבדל בין Angular ל AngularJS?
האם זה לא אותו הדבר? (תשובה: לא.)
- Angular החל כפרויקט פנימי בגוגל ב 2009, וב 2012 שוחרר לכלל התעשייה כפרויקט קוד פתוח.
- ב 2014 הצוות של Angular החליט לבצע שינויים דרמטיים לספריה, ובעצם החל לכתוב אותה מחדש, תהליך שיארוך כשנתיים. היו הרבה דרמות וויכוחים מסביב למהלך, אך כיום אפשר לומר ש AngularJS היא Legacy - ובעצם רק Angular היא רלוונטית בראיה קדימה.
- שם הספרייה החדשה היה "AngularJS 2.0" ובעצם מאז שמטו את ה JS מהשם (חשבו: TypeScript) והגרסה התקדמה. מאז השם הוא פשוט "Angular", למשל Angular 8.
בעוד AngularJS בנוי מסביב למבנה MVC (קרי: Model-View-Controller), מה שהיה מקובל באותם הימים, Angular היא ספריה שבנויה מסביב ל Component - ממש כמו ReactJS או Vue - וזה המודל הפופולארי כיום.
הערה חשובה: כאשר אתם מתייחסים למקורות באינטרנט, חשוב מאוד לבדוק האם המקור מדבר על Angular או AngularJS. אם המקור קודם ל 2016 ולא מציין ״AngularJS״ במפורש - עדיין יש סיכוי שהוא מתייחס לגרסת ה AngularJS.
יש הרבה דמיון בין הגרסאות שיכול לבלבל אותנו ולגרום לנו לחשוב שמה שאנו קוראים רלוונטי לאנגולר (החדש). למשל: ב AngularJS יש directive נפוץ בשם ng-if, אך ב Angular שינו לו את השם ל ngIf, ויש להשתמש ב directives עם סימן *. חבל לבזבז זמן ולדבג קוד של AngularJS בתוך אפליקציית Angular...
רכיבים (Components)
רכיבים הם חלק חשוב מאוד מאנגולר, אולי אבן-הבסיס המרכזית ביותר.
בואו נצלול ונראה כיצד רכיב כזה בנוי:
- נתחיל ב Metadata, הנכתב כ decorator [ב] על המחלקה. זהו בעצם המידע שהופך מחלקת TypeScript רגילה - ל Component, ומחבר עליה את כל החלקים.
- selector - ה HTML Tag שמייצג את הרכיב. כל הוספה שלו ל Markup - יוסיף את הרכיב (יש לדאוג ל imports מתאימים).
- template (אלמנט שני חשוב ברכיב) - ה HTML Markup של הרכיב, הוא חלק משמעותי ברכיב. בד"כ ינוהל כקובץ נפרד, אם כי גם ניתן לכתוב אותו כ inline בתוך ה template.
- ה Template הוא לא ה HTML הסופי שיוצג, והוא עשוי להכיל directives (אלמנט נוסף של אנגולר) ורכיבים אחרים (ע״י ציון ה Selector שלהם) המשפיעים על ה Markup הסופי. למשל ngIf directive יסיר את האלמנט שעליו הוא יושב, אם הביטוי המשויך אליו אינו חיובי.
ייתכן ובמידה והחתול של שרדינגר יריץ את הקוד - הכותרת ״Hello World!״ לא תוצג.
- style - ה S)CSS) של הרכיב. אפשר גם לכתוב inline, כאן אנו רואים קישור לקובץ.
- הסוגריים המורבעים הם מכיוון שזה מערך. ניתן להחיל על הרכיב כמה קבצי Style (אמצעי ל reuse/שיתוף של CSS).
- מי שמכיר את SMACSS - ה guidelines לכתיבת CSS, בוודאי ינטה לתת namespaces ל styles של הרכיב, בכדי שלא ישפיעו בטעות על רכיבים אחרים. אל דאגה! Angular עושה זאת בצורה אוטומטית עבורנו - ואפשר לשמור על ה markup מינימלי יותר.
- מחלקה (אלמנט שלישי חשוב ברכיב) (בד"כ ב TypeScript) - הכוללת קוד, קרי: Presentation Logic.
- בדוגמה הזו אין בכלל קוד במחלקה. אין Presentation Logic - אך עדיין יש רכיב שרץ ומציג HTML מסוים. לפעמים ה metadata הוא מספיק לרכיב - ולא צריך לכתוב קוד במחלקה.
Lifecycle Events
איזה סוג של קוד כותבים במחלקה של רכיב? כבר אמרנו: Presentation Logic, בעיקר.
מה מניע את הקוד הזה? מאיפה הוא מתחיל לרוץ? - מאירועים בחיי הרכיב, או מ Events (נדבר על Data-Binding בהמשך). הנה אותו הקוד עם מימוש של כמה מתודות נפוצות של ה Lifecycle של הרכיב:
- הוספתי את ה Lifecycle events הנפוצים ביותר. את הרשימה המלאה של Lifecycle Hooks של רכיב אנגולר ניתן למצוא כאן.
- שימו לב שלכל אירוע. המחלקה מממשת מנשק מתאים (OnInit וכו'). מכיוון שלממשקים אין ייצוג ב ES6 (הם קיימים רק ב TypeScript) אנגולר לא באמת מסתמכת עליהם בזמן ריצה. הסיבה להוסיף אותם היא לכדי לוודא שאין שגיאת כתיב בשם הפונקציה. הקומפיילר לא יתלונן אם אגדיר פונקציה בשם ngOnDestory - אבל היא לעולם לא תרוץ, ומציאת הבעיה עשויה לארוך זמן.
- כמה דגשים ספציפיים לגבי האירועים:
- ההבחנה החשובה הראשונה היא בין הבנאי ו ngOnInit. יש להרחיק מהבנאי פעולות ארכות / שעשויות להשתבש (כמו הבאת נתונים מהשרת) - ולשים אותם ב OnInit. שימוש-יתר בבנאי היא נפוצה בקרב מפתחים החדשים לאנגולר.
- כשנעסוק בנושא ה Data Binding, נראה היכן ngOnChanges מקבלת תפקיד מרכזי.
- כדי לקבל הודעות מה services של אנגולר - אנו צריכים להירשם (subscribe) אליהם. זה קוד שלרוב יקרה ב ngOnInit. כדי להימנע מ memory leak עלינו לעשות Unsubscribe ב ngOnDestory - פעולה חשובה שפעמים רבות שוכחים ממנה!
- הדבר נכון אפילו יותר לשימוש ב NGRX (מימוש דפוס ה "Redux" באנגולר) ו RxJS (ספריה פופולרית בשימוש באנגולר לתכנות ראקטיבי) - שם רישום לאירועים הוא דרך העבודה הסטנדרטית.
רכיבים מקוננים
רכיבים מקוננים הם בכל מקום באפליקציית אנגולר. אם כתבתם רכיב יחיד לכל דף - כנראה שהאפליקציה שלכם מאוד קטנה ופשוטה, או שאתם עושים משהו מאוד לא נכון.
הנה מבנה סטנדרטי של רכיבים באפליקציית אנגולר קטנה:
ורוד: התפקיד של כל קובץ ברכיב, סגול: הטווח של כל רכיב, תכלת: הטווח של כל מודול. |
בלינק הבא אתם יכולים לראות מבנה של פרויקט אנגולר פשוט אך שלם.
לאחר שהפרויקט נוצר, הוספת רכיבים או מודולים נוספים נעשית ע"י ה Angular CLI. למשל, פקודה כמו:
$ ng generate component MyComponent
גישת ה generation (או Scaffolding, כפי ש Ruby On Rails הגדירה אותה) מונעת בעיות רבות של copy-paste ועוזרת לשמור על מבנה אחיד בפרויקט. עשו מאמץ קל - והתרגלו לעבוד ב cli להוספת רכיבים חדשים לפרויקט.
בואו נראה קצת קוד, של App Component המכיל בתוכו רכיב פשוט.
הנה הקוד של ה AppComponent:
הוא מכיל בתוכו תגית שמתאימה ל selector של MyComponent:
יכולנו, באותה המידה, לכלול את MyComponent מספר פעמים.
הנה התוצאה המרשימה של האפליקציה הפעוטה שכתבתי לצורך הפוסט, כאשר הקווים האופקיים (hr) מגיעים מתוך ה AppComponent, והתוכן (כותרת ורודה וטבלה) - מגיעים מתוך ה MyComponent:
ה AppComponent לרוב יכיל רק Layout עם רכיבים אחדים: רכיבי מסגרת (header, footer, side-panel, וכו') ורכיב אחד ל"מסך"/תוכן - שישתנה תוך כדי עבודה באפליקציה (נושא של Routing - שלא אכסה בפוסט).
גם בתוך הרכיבים המתארים "מסכים", נוהגים לבנות את הרכיב העליון כרכיב רזה מבחינת UI, המכיל מספר רכיבים שמשמשים לפרזנטציה. דפוס מקובל באנגולר הוא שהרכיב העוטף (להלן: Container Component) מכיל Layout ואת הגישה לנתונים - והוא מורכב מרכיבים קטנים הנקראים Presentation Components - שמייצרים את עיקר ה Markup. רכיב ה Container אחראי להביא את הנתונים (דרך ה services, מצד השרת) - ומעביר אותם, ע"פ הצורף, לרכיבי ה Presentation - שרק עוסקים בתצוגה.
היתרונות שב Container Components:
- גישה לנתונים נעשית במקום אחד - ברכיב ה Container. קל מצוא את הקוד (LIFT). ייתכן וכך גם ניתן לגשת שרת המרוחק - פחות פעמים.
- רכיבי ה Presentation פשוטים ורק עסוקים בהצגת ה State (להלן Presentation Logic).
- קל לכתוב להם בדיקות-יחידה (מה שנקרא גם Component-Test: לבדוק את ה Markup שנוצר). אין צורך ב Mocks כי כל ה Integration Logic נמצא ברכיב ה Container.
יש חיסרון בגישה הזו, בכך שרכיבי ה Presentation הם לא עצמאיים ולא יכולים לרוץ בלי Container. למשל: הם לא Routable - כלומר: אי אפשר לשמור Bookmark למצבים ספציפיים שהם מייצגים, בלי עבודת נוספת ברמת ה routing. לא עניין גדול - לפי דעתי.
Data Binding
נושא אחרון שארצה לסקור, בזריזות, הוא נושא ה Data-Binding, היכולת לקשר בין תכונות (properties) של המחלקה ל Template בצורה ״אוטומטית״.
הנושא הזה כולו עשוי להיות מעט מבלבל, והוא ״מסתדר בראש״ בד״כ אחרי קצת תרגול בקוד. בכל זאת, אני חש שסקירה על אנגולר לא תהיה שלמה בלי לקבל מושג על היכולת הזו.
באנגולר, יש ארבע צורות של Data-Binding:
נסקור אותן (בקצרה) בזו אחר זו.
- Interpolation היא הצורה הבסיסית ביותר: אנו כותבים ביטוי בתוך סוגריים מסולסלים כפולים (מה שנקרא Mustache Style) בתוך ה Template Markup, בזמן ריצה הביטוי מחושב ותוצאתו נוספת ל HTML הסופי.
- מה שאולי קצת מיוחד, הוא שיש לנו גישה לשדות והפונקציות של המחלקה של הרכיב. במקרה הזה yourName ו ()addNumbers הם שדה ופונקציה במחלקה, בהתאמה.
- Property Binding היא צורה מתקדמת יותר המאפשרת לקשור property של אלמנט HTML לשדה במחלקה של הרכיב. למשל, image URL.
- תחביר: את ה property של ה HTML Element לו אנו רוצים לעשות binding אנו עוטפים בסוגריים מרובעים (להלן: box), והערך שמוצב הוא expression שיעבור evaluation בזמן ה binding. במקרה שלנו זהו שם של שדה על מחלקת הרכיב (יכול להיות גם פונקציה, או כל ביטוי ב ג'אווהסקריפט).
- יכולנו לכתוב את אותו הביטוי כ interpolation:
<""=img src={{imgUrl}} alt> - התוצאה של חישוב ביטוי ב interpolation - תמיד תהיה מחרוזת. אם יש property מטיפוס אחר (למשל: disabled הוא property מטיפוס Boolean) - עלינו להשתמש ב Property Binding. מחרוזת שאינה ריקה ב js - תחשוב כ true. כלומר: גם "false" היא true. אופס!
- ה Property Binding מאפשר לנו לגשת לתכונות מקוננות, מה שמאוד קשה לעשות עם interpolation. למשל, לקבוע רוחב של תמונה:
< "img [src]="imgUrl" [style.width.px]="imageWidth> - התכונה הזו נקראת "Style binding", אבל יש גם class binding או attribute binding ועוד...
- Event Binding היא היכולת להגיב ל Browser Event בתוך המחלקה של הרכיב. במקום שנכתוב inline javaScript בתוך ה Template (פרקטיקה רעה לתחזוקה) - אנו נעטוף את שם האירוע שאנו רוצים לטפל בו בסוגריים עגולים, ואז נציב לתוכו ביטוי שיהווה את ה handler באירוע. בד"כ: הפעלה של פונקציה.
- לעתים אנו רוצים גם להציג תכונה של המחלקה ב UI, וגם לתת ל UI לשנות את הערך - ולעדכן את המחלקה. היכולת הזו מתאפשרת בקלות בעזרת Two-Way-Data-Binding (בקיצור: 2WDB) יכולת שעוד זכורה לטובה מ AngularJS (אם כי היא גם זכורה לרעה, בשל שימוש יתר).
- בקיצור: אפשר לקצר 2 ביטויי bindings שנראים כך:
[value]="view.value" (valueChange)="view.value = $event"
- לביטוי המקוצר הבא: "value)]="view.value)].
האופרטור נקרא "Banana in a box" בכדי להזכיר שהסוגריים העגולים הם פנימיים לסוגריים המרובעים. - השימוש הנפוץ של 2WDB הוא בטפסים (Forms), כאן בא לשימוש Angular Forms (מודול אופציונלי של Angular) שניתן להוסיף לאפליקציה, ואז להשתמש ב directive בשם ngModel המקל את העבודה עם 2WDB וטפסים. בשימוש ב ngModel יש לזכור להוסיף את FormsModule ל import של ה NgModule שלנו.
- בדוגמה למעלה, חיברנו את 2 השדות name ו age של מחלקת הרכיב לשדות input.
- כל שינוי ב UI - יעדכן את ערך השדה באובייקט (ויקפוץ את האירוע: ngOnChnages)
- שינוי בערך השדה מתוך הקוד - יעדכן את ערך השדה ב UI.
- בדוגמת הקוד למעלה גם שילבתי pipe, רכיב באנגולר שבצע formatting ל output של שדות.
ה pipes הם יכולת משלימה ל data binding מכיוון שיש פער בין האופן שבו אנו רוצים להחזיק את הנתונים במחלקה - ובאופן שאנו רוצים להציג אותם ב UI. למשל: formatting של Date. ישנם כמה pipes מובנים באנגולר, ואתם יכולים לכתוב custom pipes משלכם - לשימוש חוזר ואחיד באפליקציה. - ה Titlecase pipe הופך את המחרוזת ל lowerCase מלבד אות ראשונה בכל מילה שתהיה Capital. מה שלעתים נקרא גם humanize.
כל דוגמאות הקוד שלי לגבי data binding נלקחו מהפוסט הזה שמכסה בצורה תמציתית (אך רחבה יותר ממה שאני כיסיתי) את נושא ה Data Binding.
סיכום
כפי שאתם רואים, אנגולר היא ספריה דיי משמעותית, ויש הרבה מה ללמוד לגביה.
קרוב לוודאי שהפוסט הזה לא הפך אתכם למפתחי אנגולר, אך ניסיתי לתת סקירה משמעותית על הספרייה ואופיה - בזמן קצר. מקווה שהצלחתי.
שיהיה בהצלחה!
----
לינקים רלוונטיים
השוואה בין אנגולר ל React. מה ההבדל? מה הדמיון?
----
[א] why you might NOT want to use TypeScript - חלק א', חלק ב'.
[ב] Decorators ב TypeScript הם כמו Attributes ב #C או Annotations בג׳אווה: דרך להגדיר metadata על רכיב בשפה. במידה ועובדים עם ES5 - יש workaround אחר.
[ב] Decorators ב TypeScript הם כמו Attributes ב #C או Annotations בג׳אווה: דרך להגדיר metadata על רכיב בשפה. במידה ועובדים עם ES5 - יש workaround אחר.
תגובה זו הוסרה על ידי המחבר.
השבמחקתודה רבה! מאז עברתי ל vue...
השבמחק👍
מחקמדהים. תודה על הסקירה!
השבמחקסקירה מעולה, תודה
השבמחקמעולה ממש. כתוב בצורה בהירה ומובנת.
השבמחקתודה.
תודה רבה לכולם!
השבמחקפוסט מעולה,יש לי קצת נסיון אבל עדיין עושה סדר טוב.
השבמחקנדיר לראות כאלה אכויות בעברית
תודה על הסקירה!
השבמחק