RSS

קטגוריה: Uncategorized

Angular 2 The Clock Component

באנגולר 2 אחרי כל אירוע אסינכרוני יש tick שנקרה ע"י ה-zone. אם יש הרבה אירועים אסינכרוניים בשנייה אנחנו יכולים לגרום לבעיית ביצועים.

בפוסט זה אני רוצה להסביר איך לכתוב רכיב שעון בדיוק של 50 ms. בחרתי את הקוד הבסיסי  לשעון שלי:

setTime(){
let t = new
Date();
this.time =
`
${t.getHours()}

        :
${this.formatNum(t.getMinutes())}
        :
${this.formatNum(t.getSeconds())}
        :
${t.getMilliseconds()}`;
setTimeout(
this.setTime.bind(this),50
);
}
formatNum(i){
return i < 10 ? `0${i}`
: i; }

 

שימו לב:

אני משתמש ב- setTimeout ולא ב- setInterval כדי לא ליצור עומס על ה- queue במידה וה- UI Thread עמוס ואז הוא לא מצליח למשוך מהתור את הפונקציות בקצב שה- setInterval מיצר אותם.

 

שלב א: לעבוד מחוץ לאנגולר

אני לא רוצה שכל 50 ms יבוצע tick במערכת. (המשמעות של tick  היא שאנגולר עובר על עץ הרכיבים ובודק מה השתנה ואז מעדכן את ה- UI. ראו פוסטים בנושא. ) לכן אני אשתמש ברכיב ה- NgZone.

constructor(zone:NgZone) {}
ngOnInit(){
    this.zone.runOutsideAngular(()=> {
        this.setTime();
    });
}
 
הקוד הנ"ל מוציא את ה- setTimeout ממנגנון ה- zone. כלומר עכשיו ה- 50 ms לא גורמים ל- tick.
 

שלב ב: לעדכן את המסך

אני אשתמש ביכולות של ה- ChangeDetectorRef והפונקציה detectChanges, מחשבת את כל החלקים הדינאמים בתבנית (למשל {{}} או [] ). ראו קוד:

@Component({
    selector: 'clock',
    template: `<span>{{time}}</span>`
})
export class Clock extends BaseDemo{
    time:string = '00:00:00:000';
    isDestroy:boolean = false;
    constructor(zone:NgZone,
                cd:ChangeDetectorRef) {}
    ngOnInit(){
        this.cd.detach();
        this.zone.runOutsideAngular(()=> {
            this.setTime();
        });
    }
    setTime(){
        if(this.isDestroy) return;
        let t = new Date();
        this.time = `
            ${t.getHours()}
            :${this.formatNum(t.getMinutes())}
            :${this.formatNum(t.getSeconds())}
            :${t.getMilliseconds()}`;
        this.cd.detectChanges();
        setTimeout(this.setTime.bind(this),50);
    }
    formatNum(i){ return i < 10 ? `0${i}` : i; }
    ngOnDestroy(){
        this.isDestroy = true;
    }
}

 

סיכום:

יש הרבה רכיבים שיש להם תדירות גבוהה של עדכון מסך. שימוש ברכים אלו יגרמו ל- tick שיגרום לעדכן את כל האפלקציה. בפוסט זה אני מראה לכם איך לשלוט בתדר העידכון ע"י ניתוק מה- zone וקריאה ל- detectChanges כל פעם שרוצים לעדכן את הרכיב על המסך. עדכון זה לא גורם ל- tick.

כמו תמיד אשמח לפידבקים.

למידע נוסף בנושא, אשמח לראות אותכם בקורס אנגולר  2 שלי ng-course.

מודעות פרסומת
 
תגובה אחת

פורסם ע"י ב- יוני 25, 2016 ב- Angular 2.0, Uncategorized

 

The New Router

ראיתי את המצגת של מישקו בנושא ה-router החדש והתאכזבתי.

 

ההרגשה שזה תוכנן ברגע האחרון ולא חשבו מספיק על כל מקרי הקצה של אפליקציות גדולות מאוד.

 

1. באתרים גדולים העץ כל כך גדול שה-URL לא יכול לייצג את ה-PATH של העץ, מגבלת אורך. אני מאמין שזה הסיבה שב- UI Router קראו לזה State ואנחנו יכולנו לקבוע לכל State את ה-Path שלו.

 

2. הרעיון של תיקיות עם "+"  זה נחמד ברוב המקרים, אך יש מקרים שהכל דינאמי והקשר בין ה-URL למבנה התיקיות מאוד מגביל. אני חושב שאנחנו צריכים קובץ מיפוי בין ה-URL לאיפה נמצאים ה- Components.

 

האמת שאני מואד אוהב את ה- UI Router וחשבתי שהם ישפרו אך ישמרו על העקרונות. מקווה שבקרוב נראה גירסה יותר מתקדמת של UI Router לאנגולר 2.0.

 

מה אתם חושבים?

 
השארת תגובה

פורסם ע"י ב- מאי 7, 2016 ב- Uncategorized

 

Angular 2.0 Component Decorator

 

בפוסט זה אני רוצה להסביר את כל הפרטים הטכנים על @Component.

כאשר אנחנו כותבים באנגולר מחלקה מסוג component אנחנו חייבים להוסיף @Component עם כל הפרטים, כמו למשל selector, template וכ"ו. הפונקציה Component יוצרת מהמידע הנ"ל מחלקה בשם ComponentMetadata ושומרת את המידע כ-metadata על המחלקה.

: Reflect Metadata API

אנגולר 2 משתמש ב-Reflect Metadata כדי לשמור את המידע שנתנו ב- @Component.  כאן אנגולר מגדיר את הפונקציה Component. והפונקציה makeDecorator משתמש ב-Reflect Metadata כדי לאחסן את המידע ביחד עם המחלקה שלכם.

למה זה מעניין?

בעיה: רוצים לרשת מחלקה מסוג Component וגם את הגדרות שלה ב-@Component.

פתרון:

כתבתי decorator חדש , ngExComponent שיכול לקבל arg נוסף של מחלקה. ה- ngExComponentקורא את ה-metadata מהמחלקה וממזג אותם עם ה-metadata של המחלקה היורשת. ראו קוד:

export function ngExComponent(metadata,component?){
   
var
merageMetadata = component?
        Object.assign(getComponentMetadata(component),metadata):
        metadata;
   
return
Component(merageMetadata);
}

 

דוגמא לשימוש:

@Component({
    selector:'users',
    providers:[UserProxy],
    directives: [User],
})
class BaseUser{}
// Derive class
@ngExComponent({     template: `...`
},BaseUser) export class User extends BaseUser{ ... }
 
הסברים:
היתרון בשיטה זו שאני יכול במחלקה BaseUser להגדיר את כל ה-metadata המשותפים לכל סוגי 
ה-User. המחלקה היורשת יכולה לדרוס את ה-metadata שהיא צריכה.
 
לקוחות שלא אוהבים לעבוד עם ngExComponent, אני מוסיף למחלקה העליונה מתודה סטטית
 בשם getMetadata, ראו קוד:
@Component({
    selector:'users',
    providers:[UserProxy],
    dirctives: [User],
})
class BaseUser{
    static getMetadata():ComponentMetadata{
        var result;
        Reflect.getMetadata('annotations', BaseUser)
            .forEach(metadata => {
                if (metadata.constructor.name === 'ComponentMetadata'){
                    result =  metadata;
                }
            });
        return result;
    }
}
 

בעיה: איך משנים בזמן ריצה את ComponentMetadata, כמו למשל templateUrl או styleUrls?

 

פתרון:

אנגולר משתמש בשרותים מסוג Resolvers כדי לקרוא את ה-metadata של Component.

clip_image002

אנחנו יכולים לדרוס את שירותים אלו ואז לעשות מניפולציה על הנתונים לפני שאנגולר משתמש בהם. קראו פוסט שכתבתי בנושא. פתרון זה מאפשר לי להגדיר ל- Component  אחת ומספר views, למשל.

 

אשמח לקבל פידבקים J

נושאים אלו אני מלמד בקורס שלי Angular 2.0 Development לפרטים נוספים לחצו כאן.

 

 
4 תגובות

פורסם ע"י ב- אפריל 21, 2016 ב- Uncategorized

 

Angular 1.x vs. Angular 2.x

תודה לכל האנשים שבאו אתמול ל-meetup. להוריד את הקוד לחצו כאן.

הרצאה זו לקוחה מתוך הקורס שלי על Angular 2.

תאריכים של פתיחת קורס על Angular 2:

1. בחודש מאי 9,16,23,30 (ימי שני ) לינק לרישום, בירושלים.

2. בחודש יוני, 19,22,26,29 בהרצליה.

 
השארת תגובה

פורסם ע"י ב- אפריל 13, 2016 ב- Uncategorized

 

Angular Injector Round III

בפוסט זה אני מראה איך אפשר לוותר היום על ה- Injector !!! לא נפלתי על הראש (מקווה). בזמן האחרון אני כותב אנגולר 1.x ו-2.0 עם ES 6 או TS, והתחושה שה- Injector פשוט מיותר לגמרי באנגולר 1.0 עם כותבים ב- ES 6.

המטרות של ה- Injector באנגולר 1:

1. הזרקת השירותים שאני רוצה בלי להכיר את המימוש וע"י כך מקל אלי בבדיקות.

2. ה- Injector עובד כ- lazy initialization, עד שלא מבקשים שירות הוא לא נוצר. ראו סרט בנושא.

 

איך מפסיקים להשתמש ב-Injector של אנגולר?

1. בונים תחליף שמשמש כגשר בין השרותים של אנגולר לשרותים שלנו להלן יקרה ngServices.

2. ngServices צריך לתת לי גישה לכל השרותים של אנגולר שהם singleton, שזה כולם חוץ מ- $scope ו- $element. ( אם שכחתי, אנא תעירו לי ).

 // ngServices.js
export var ngServices = {
    $injector : null
};

export function addAngularServices() {
    for(let i = 0; i < arguments.length ; i++){
        let serviceName = arguments[i];
        Object.defineProperty(ngServices,serviceName,{
            get(){
                return ngServices.$injector.get(serviceName);
            }
        });
    }
}

export function ngServicesConfig($injectorProvider){
ngServices.$injector = $injectorProvider.$get();
}

 

 

כאשר אני רוצה לרשום שרות אני משתמש  בפונקציה addAngularServices. השרותים שאני נותן לפונקציה זו חייבים להיות רשומים גם באנגולר.

כאשר רוצים לצרוך שרות עושים import ל- ngServices. ראו דוגמא של שרות userProxy שצורך שרותי אנגולר בסיסיים כמו $http.

Capture

הסברים:

שאתם רוצים לכתוב שרות או סתם מחלקה אתם לא צריכים לרשום אותה יותר לאנגולר. אם אתם רוצים להשתמש בשרותים שרשומים באנגולר אתם צורכים אותם דרך ngServices.

כדי ש- ngServices יוכל לצרוך שרותים של אנגולר ולחשוף אותם דרכו את צריכים להוסיף את השורה הבאה למודול הראשי שלכם.

 

import angular from 'angular';
import {ngServicesConfig} from './utils/ngServices'
;

angular.module('app',[])
.config(ngServicesConfig);

 

סיכום:

אני מאמין שברגע שמשתמשים ב-import (systemjs) אין צורך לרשום את השרותים שלנו לתוך המודלים של אנגולר 1. הראתי שזה לא פוגע בשום יכולת קיימית אלה רק מקל אלינו את הפיתוח ומוריד את התלות באנגולר אחד. אני מאמין שזה יקל אלינו גם בשידרוג לאנגולר 2.

 

יש אפשרות לבצע את אותו טריק גם באנגולר 2, אך זה כבר פוסט אחר.

 

צריך לזכור שזה קוד ראשוני ועוד לא עבר את כל הבדיקות לכן אשמח לקבל הערות.

 
2 תגובות

פורסם ע"י ב- מרץ 31, 2016 ב- Uncategorized

 

Async and Parallel in JavaScript (meetup)

תודה לכל האנשים שבאו.  מצ"ב הלינק למצגת.

 
השארת תגובה

פורסם ע"י ב- ינואר 13, 2016 ב- Uncategorized

 

The Power Of ngModelController

בפוסט זה אני רוצה להציג תרגיל קטן שמדגים את היכולות של ngModel ובעיקר את היכולות של ה- controller שלו, ngModelController.

מטרת התרגיל:

1. להדגים את היכולות של $formatters ו- $parsers, ע"י שינוי מבנה הנתונים שעוברים בין ה-DOM והמודל.

2. להדגים את היכולות של $render, ע"י חיבור דו כיווני שלא באמצעות input תג.

הסברים: ( code )

1. אני בונה directive בשם box שהוא סוג חדש של data-binding.

2. אני משתמש ביכולות של ngModelController ולכן אני צריך לכתוב require : ngModel. קונטרולר זה מוזרק לי כארגומנט רביעי בפונקצית ה-link.

3. אני משתמש ב-  $formatters ו- $parsers כדי לעביר ממבנה נתונים אחד (מודל) למבנה נתונים שני ה- UI.

4. אני משתמש ב- $render כדי להסביר ל-ngModelController איך הוא מעדכן את ה-DOM, זה לא input תג.

5. אני משתמש ב- Drag & Drop כדי לעדכן את המיקום של ה-div.

6. יתרון בעבודה עם ngModelController שהוא מביא איתו עוד הרבה יכולות נוספות כמו בדיקות תקינות ומכונת מצבים של תקין כן/לא, עבר שינוי כן/לא, הודעות שגיאה ועוד.

למידה נוסף ראו את המצגת  או הפוסט.

 
השארת תגובה

פורסם ע"י ב- נובמבר 18, 2015 ב- Uncategorized