1. מבוא
מאת Aayush Arora, מחבר אורח
Angular Elements הם רכיבי Angular שנארזו כרכיבים מותאמים אישית. הם נתמכים כרגע על ידי Chrome, Opera ו-Safari, וזמינים בדפדפנים אחרים באמצעות polyfills. האלמנטים האלה יכולים להשתמש בתשתית Angular כולה עם ממשק Angular משותף ואסטרטגיית זיהוי שינויים. אחרי הרישום, אפשר להשתמש ברכיבים האלה בדפדפן.
ב-codelab הזה נסביר איך ליצור רכיב Angular משלכם להצגת תמונות במצגת שקופיות, ואז נסביר איך להפוך אותו לרכיב Angular כדי שיוכל לפעול מחוץ למסגרת Angular.
מה תפַתחו
ב-codelab הזה תלמדו איך ליצור רכיב של סליידר תמונות באמצעות Angular. האלמנט שלך wi:
|
מה תלמדו
- איך יוצרים רכיב בהתאמה אישית של קרוסלת תמונות
- איך משנים את הרכיב המותאם אישית image-slider לרכיב מותאם אישית
- איך לארוז את הרכיב כך שהוא יפעל בדפדפן
מה צריך להכין
- גרסה עדכנית של angular-cli.
- קוד לדוגמה
- כלי לעריכת טקסט
- ידע בסיסי ברכיבי Angular
ה-codelab הזה מתמקד ב-Angular Elements. מושגים וקטעי קוד לא רלוונטיים מוצגים בקצרה, ואתם יכולים פשוט להעתיק ולהדביק אותם.
2. תהליך ההגדרה
הורדת הקוד
כדי להוריד את כל הקוד של ה-Codelab הזה, לוחצים על הקישור הבא:
מחלצים את קובץ ה-ZIP שהורד. הפעולה הזו תפרוס תיקיית שורש (angular-element-codelab-master)
, שמכילה
שתי תיקיות (image-slider)
ו-(image-slider-finished)
. כל עבודת התכנות שלנו תתבצע בספרייה שנקראת image-slider.
הפעלת הפרויקט
כדי להריץ את הפרויקט, צריך להריץ את הפקודה ( ng-serve ) מהספרייה הבסיסית ( image-slider ).
אחרי שהאפליקציה תופעל, תוכלו לראות את הדברים הבאים:
3. רוצה ליצור רכיב בהתאמה אישית של תמונות מתחלפות?
איך יוצרים סליידר של תמונות?
במקרה של קרוסלת התמונות הזו, צריך לקשור את הכפתורים באמצעות קשירת קליקים של Angular. ניצור מערך של אובייקטים שמכילים תמונות, תגי alt, קישורים וכו'. נציב את התמונות האלה אחת מתחת לשנייה בקונטיינר ונתרגם את הקונטיינר בלחיצה.
אנחנו ניצור רכיב של קרוסלת תמונות ואז נהפוך אותו לרכיב Angular.
- קונטיינר של תמונות וכותרות.
- מערך שמכיל את הנתונים
- תבנית לאיגוד הנתונים
4. הטמעה של רכיב image-slider
יש כמה דרכים להתחיל כל פרויקט. במקרה הזה, כדי שהפרויקט שלנו יהיה פשוט ככל האפשר ונוכל להתרכז ב-Angular Elements, סיפקנו לכם קוד בסיסי יחד עם ה-CSS.
יצירת מערך ושירות נתונים
חשוב לזכור שהמערך sliderArray יכיל:
- מפתח img לכתובת ה-URL של התמונה בסליידר
- תג alt כדי לספק טקסט חלופי לתמונה
- טקסט שמשמש לתיאור התמונה
קובץ data.json
שכבר נמצא בספרייה src/assets
אמור להיראות בערך כך.
sliderArray = [
{img: 'http://bloquo.cc/img/works/1.jpg', alt: '', text: '365 Days Of weddings a year'},
{img: 'http://bloquo.cc/img/works/2.jpg', alt: '', text: '365 Days Of weddings a year'},
{img: 'http://bloquo.cc/img/works/3.jpg', alt: '', text: '365 Days Of weddings a year'},
{img: 'http://bloquo.cc/img/works/4.jpg', alt: '', text: '365 Days Of weddings a year'},
{img: 'http://bloquo.cc/img/works/5.jpg', alt: '', text: '365 Days Of weddings a year'}
];
אנחנו צריכים לאחזר את הנתונים האלה ברכיב שלנו באמצעות שירות. בקובץ data.service.ts
, נכתוב method getData()
באמצעות המודול httpClient
מ-@angular/common/http
, שיאחזר את הנתונים מהמערך שיצרנו למעלה.
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http'
const URL = '../assets/data.json';
@Injectable({
providedIn: 'root'
})
export class DataService {
constructor(private http: HttpClient) {}
getData() {
return this.http.get(URL)
}
}
אחזור הנתונים משירות הנתונים
צריך לייבא את השירות לרכיב ואז להירשם ל-Observable כדי לקבל את האובייקט מ-data.json
כדי לעשות זאת, צריך לבצע שלושה שלבים:
- הגדרה ראשונית של מערך רכיבים
- הרשמה ל-Observable שמוחזר על ידי הפונקציה
getData()
- יוצרים ממשק Result כדי לבדוק את סוג הנתונים אחרי ההרשמה ל-Observable.
- מקצים את הנתונים למערך הרכיבים.
אתחול מערך רכיבים
נצהיר על מערך הרכיבים ונאתחל אותו בתוך slider.component.ts
, שהוא מערך של אובייקטים:
כדי להצהיר:
sliderArray: object[];
כדי להפעיל:
constructor(private data: DataService) {
this.sliderArray = [];
}
בשלב הבא, צריך לייבא את השירות ולהפעיל אותו בתוך ה-constructor
constructor(private data: DataService) {}
עכשיו אנחנו מוכנים להשתמש בשירות שלנו ולהתקשר לשיטות השירות שלנו.
קבלת נתונים משירות הנתונים
כדי להוציא את הנתונים מהשירות, נקרא למתודה getData()
ונרשם ל-observable שהיא תחזיר. ניצור גם ממשק Result,
כדי שנוכל לבדוק את סוג הנתונים שאנחנו מקבלים.
נעשה את זה בתוך שיטת ngOnInit
:
this.data.getData().subscribe((result: Result)=>{
})
הקצאת נתונים למערך רכיבים
בסוף, נשייך את הנתונים למערך הרכיבים:
this.data.getData().subscribe((result: Result)=>{
this.sliderArray = result.sliderArray;
})
אחרי שהנתונים יגיעו למערך של הרכיב, נוכל לקשר את התבנית לנתונים האלה.
ב-slider.component.html,
כבר יש לנו תבנית HTML. השלב הבא הוא לקשר את התבנית הזו אל sliderArray
.
5. קישור הנתונים לתבנית
נקשר את הנתונים לתבנית באמצעות Directive *ngFor
, ולבסוף נוסיף לתבנית טרנספורמציות כדי שהסליידר יפעל.
התהליך הזה כולל שלושה שלבים:
- קישור
sliderArray
לתבנית - הוספת Event Binding לכפתורים של פס הזזה
- הוספת טרנספורמציות CSS באמצעות
ngStyle
ו-ngClass
קישור של slideArray לרכיב
יש לנו מאגר שמכיל img-container
, a
text-container
ו-a
slider.
נקשר את הנתונים בכל שלושת המאגרי באמצעות ההנחיה *ngFor
<div class="container">
<div class="img-container" *ngFor="let i of sliderArray; let select = index;">
<img src="{{i.img}}" alt="{{i.alt}}" >
</div>
<div>
<div class="text-container">
<div class="page-text" *ngFor="let i of sliderArray;let select = index;">
<h3>{{i.text}}</h3>
</div>
</div>
</div>
</div>
<div class="slider">
<div class="slide-button-parent-container" *ngFor="let i of sliderArray; let x =index">
<div class="select-box">
<div class="slide-button">
</div>
</div>
</div>
</div>
קישור אירועים ל-slideArray
אחרי שהנתונים משויכים, נשייך את אירוע הקליק לכל לחצן הזזה באמצעות angular click binding
. ניצור פונקציה בשם selected(x)
כאשר x הוא האינדקס של המערך.
selected(x) {
this.downSelected(x);
this.selectedIndex = x;
}
downSelected(i) {
this.transform = 100 - (i) * 50;
this.selectedIndex = this.selectedIndex + 1;
if(this.selectedIndex > 4) {
this.selectedIndex = 0;
}
}
נקודות שחשוב לזכור:
- הפונקציה שנבחרה מצמצמת את הערך של מאפיין הטרנספורמציה פי חמישים מהאינדקס שמועבר בלחיצה על הפונקציה
selected
. - הלוגיקה הזו מתרגמת את מאגר הטקסט ל-100%, ל-50%, ל-50%- ול-100%-, וכך מתקבלים ארבעה מצבים שונים.
הוספת טרנספורמציות של CSS באמצעות ngStyle ו-ngClass
בתחילה אנחנו מגדירים את כל התמונות עם אטימות של אפס, ומוסיפים מחלקה selected
באמצעות ngClass directive
כשהאינדקס שנבחר שווה לאינדקס התמונה. הסיווג selected
הזה מוסיף לתמונה אטימות של אחד, וכך התמונה גלויה למשתמש.
<div class="img-container" *ngFor="let i of sliderArray; let select = index;"
[ngClass]="{'selected': select == selectedIndex}">
</div>
לאחר מכן, נתרגם את text-container בהתאם לערך transform
שחושב באמצעות הפונקציה select()
.
<div [ngStyle]="{'transform': 'translateY('+ transform + '%' +')', 'transition': '.8s'}">
</div>
אחרי שתבצעו את כל השלבים האלה, תוכלו לראות את הקוד הסופי כמו שמופיע בהמשך:
<div class="container">
<div class="img-container" *ngFor="let i of sliderArray; let select = index;"
[ngClass]="{'selected': select == selectedIndex}">
<img src="{{i.img}}" alt="{{i.alt}}" >
</div>
<!--</div>-->
<div [ngStyle]="{'transform': 'translateY('+ transform + '%' +')', 'transition': '.8s'}">
<div class="text-container">
<div class="page-text" *ngFor="let i of sliderArray;let select = index;" [ngClass]="{'selected': select == selectedIndex}">
<h3>{{i.text}}</h3>
</div>
</div>
</div>
</div>
<div class="slider">
<div class="slide-button-parent-container" *ngFor="let i of sliderArray; let x =index" (click)="selected(x)" >
<div class="select-box">
<div class="slide-button" [ngClass]="{'slide-button-select': x == selectedIndex}" >
</div>
</div>
</div>
</div>
6. הפיכת הרכיב לרכיב Angular
התהליך הזה כולל חמישה שלבים:
- שימוש ב-
Shadow DOM
לרכיב Angular - שימוש ב-
entryComponents
- ייבוא של המודול
CreateCustomElement
מ-@angular/elements
ושימוש בו - הגדרת
custom-element
- שיטת ההפעלה
ngDoBootstrap
שימוש ב-Shadow DOM עבור רכיב Angular
עכשיו יש לנו קרוסלת תמונות, וצריך רק להפוך אותה ל-Angular Element
.
החלק המעניין הוא שצריך לבצע רק שינוי קטן כדי להפוך את רכיב ה-DOM ל-Shadow DOM.
צריך לייבא את המודול ViewEncapsulation
ולהשתמש בשיטה ShadowDom
שלו.
@Component({
selector: 'app-slider',
templateUrl: './slider.component.html',
styleUrls: ['./slider.component.css'],
encapsulation: ViewEncapsulation.ShadowDom
})
שימוש ב-entryComponents
רכיב הכניסה הוא רכיב ש-Angular טוען באופן אימפרטיבי. מציינים רכיב כניסה על ידי הפעלת bootstrapping שלו ב-NgModule.
כאן נציין את SliderComponent
במערך entryComponents
בתוך @NgModule
@NgModule({
declarations: [
SliderComponent
],
imports: [
BrowserModule,
HttpClientModule
]
})
ייבוא של מודול createCustomElement ושימוש בו
כאן צריך להשתמש ב-createCustomElement
Module מתוך @angular/elements.
צריך להשתמש ב-SliderComponent,
כפרמטר לפונקציה createCustomElement
. לאחר מכן, צריך לרשום את slider
ב-DOM.
import { createCustomElement } from '@angular/elements';
export class AppModule {
constructor(private injector: Injector) {
const slider = createCustomElement(SliderComponent, { injector });
}
}
כדי לרשום את פס ההזזה כרכיב DOM, נגדיר אותו באמצעות השיטה customElements.define
.
customElements.define('motley-slider', slider);
לבסוף, צריך להפעיל את הרכיב המותאם אישית הזה באמצעות השיטה ngDoBootstrap()
. הקוד המלא ייראה כך:
import { BrowserModule } from '@angular/platform-browser';
import { NgModule, Injector } from '@angular/core';
import { createCustomElement } from '@angular/elements';
import { SliderComponent } from './slider/slider.component';
import { HttpClientModule} from "@angular/common/http";
@NgModule({
declarations: [
SliderComponent
],
imports: [
BrowserModule,
HttpClientModule
]
})
export class AppModule {
constructor(private injector: Injector) {
const slider = createCustomElement(SliderComponent, { injector });
customElements.define('motley-slider', slider);
}
ngDoBootstrap() {}
}
אריזת רכיב Angular
צריך לשנות את הקובץ package.json
באמצעות הפקודות החדשות. לשם כך, נשנה את אובייקט הסקריפט בקובץ package.json
.
נבדוק את אובייקט הסקריפט ששינינו:
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build --prod --output-hashing=none",
"package": "cat dist/my-app/{runtime,polyfills,scripts,main}.js | gzip > elements.js.gz",
"serve": "http-server",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e"
}
עכשיו אפשר להריץ את הפקודה ng build & ng package
, ובסיום נריץ את הפקודה ng serve כדי להציג את התיקייה dist/ שנוצרה באמצעות פקודת ה-build. בנוסף, אנחנו יכולים להשתמש בgzip
שמתקבל מהפקודה ng package
, לחלץ אותו ולפרסם אותו כnpm module
.