เกี่ยวกับ Codelab นี้
1 บทนำ
ผู้เขียนโดย Aayush Arora
องค์ประกอบ Angular คือคอมโพเนนต์ Angular ที่บรรจุเป็นองค์ประกอบที่กําหนดเอง ปัจจุบัน Chrome OS, Opera และ Safari รองรับฟีเจอร์ดังกล่าว และมีให้บริการในเบราว์เซอร์อื่นผ่าน Polyfill องค์ประกอบเหล่านี้ใช้ประโยชน์จากโครงสร้างพื้นฐานของ Angular ทั้งหมดได้ด้วย Angular Interface และ Detection Strategy ที่พบบ่อย เมื่อลงทะเบียนแล้ว คุณจะใช้องค์ประกอบเหล่านี้ได้ในเบราว์เซอร์
Codelab นี้จะแนะนําการสร้างคอมโพเนนต์แบบเหลี่ยมมุมของแถบเลื่อนของคุณเอง และจะช่วยให้คุณเปลี่ยนรูปแบบเป็นองค์ประกอบแบบเหลี่ยมมุมเพื่อให้ทํางานนอกเฟรมเวิร์ก Angular ได้
สิ่งที่คุณจะสร้าง
ใน Codelab นี้ คุณจะสร้างองค์ประกอบแถบเลื่อนรูปภาพโดยใช้มุม องค์ประกอบของคุณกับ wi:
|
สิ่งที่จะได้เรียนรู้
- วิธีสร้างคอมโพเนนต์แถบเลื่อนที่กําหนดเอง
- วิธีเปลี่ยนคอมโพเนนต์ที่กําหนดเองของแถบเลื่อนรูปภาพเป็นองค์ประกอบที่กําหนดเอง
- วิธีจัดแพ็กเกจคอมโพเนนต์เพื่อให้ทํางานในเบราว์เซอร์
สิ่งที่ต้องมี
- angular-cli เวอร์ชันใหม่ล่าสุด
- โค้ดตัวอย่าง
- เครื่องมือแก้ไขข้อความ
- ความรู้พื้นฐานของคอมโพเนนต์ Angular
Codelab นี้มุ่งเน้นที่องค์ประกอบ Angular แนวคิดที่ไม่มีความเกี่ยวข้องและการบล็อกโค้ดจะไม่เพียงพอ และคุณก็มีหน้าที่คัดลอกและวางเท่านั้น
2 การเริ่มตั้งค่า
ดาวน์โหลดโค้ด
คลิกลิงก์ต่อไปนี้เพื่อดาวน์โหลดโค้ดทั้งหมดสําหรับ Codelab นี้:
คลายการคลายไฟล์ ZIP ที่ดาวน์โหลด การดําเนินการนี้จะเปิดเผยโฟลเดอร์รูท (angular-element-codelab-master)
ซึ่งประกอบด้วย
2 โฟลเดอร์ (image-slider)
และ (image-slider-finished)
โดยเราจะทําการเขียนโค้ดทั้งหมดในไดเรกทอรีที่เรียกว่าแถบเลื่อนรูปภาพ
การดําเนินโครงการ
หากต้องการเรียกใช้โปรเจ็กต์ คุณต้องเรียกใช้คําสั่ง ( ng-serve ) จากไดเรกทอรีราก ( image-slider)
เมื่อบูตแอปแล้ว คุณจะเห็นรายการต่อไปนี้
3 การสร้างคอมโพเนนต์ที่กําหนดเองของแถบเลื่อนรูปภาพ
วิธีสร้างแถบเลื่อนรูปภาพ
สําหรับแถบเลื่อนรูปภาพนี้ ปุ่มเชื่อมโยงโดยใช้การเชื่อมโยงการคลิกแบบเหลี่ยมมุม เราจะสร้างอาร์เรย์ของออบเจ็กต์ที่มีรูปภาพ แท็ก Alt ลิงก์ ฯลฯ เราจะวางรูปภาพเหล่านี้ไว้ด้านล่างๆ ในคอนเทนเนอร์ และแปลคอนเทนเนอร์เมื่อคลิก
เราจะสร้างคอมโพเนนต์แถบเลื่อนรูปภาพเพื่อเปลี่ยนรูปแบบเป็นองค์ประกอบแบบเหลี่ยมมุม
- คอนเทนเนอร์สําหรับรูปภาพและชื่อ
- อาร์เรย์ที่มีข้อมูล
- เทมเพลตเพื่อเชื่อมโยงข้อมูล
4 ใช้คอมโพเนนต์แถบเลื่อนรูปภาพ
สําหรับการเริ่มต้นทําโครงการใดๆ ได้หลายวิธี วิธีที่เราทําให้โครงการของเราเรียบง่ายที่สุดและเน้นที่องค์ประกอบ Angular เราได้ให้รหัสพื้นฐานแก่คุณพร้อมกับ CSS
การสร้างอาร์เรย์และบริการข้อมูล
แถบเลื่อนคือแถบเลื่อนที่มี
- คีย์ img สําหรับ URL ของรูปภาพในแถบเลื่อน
- แท็ก Alt เพื่อระบุ 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
เราจะเขียนเมธอด 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)
}
}
การดึงข้อมูลจากบริการข้อมูล
เราต้องนําเข้าบริการของเราภายในคอมโพเนนต์เพื่อให้เราสมัครรับข้อมูลที่สังเกตได้เพื่อรับออบเจ็กต์จาก data.json
เราจําเป็นต้องดําเนินการ 3 ขั้นตอนดังนี้
- การเริ่มต้นอาร์เรย์คอมโพเนนต์
- การสมัครใช้บริการ"การสังเกตการณ์"ที่แสดงผลโดยฟังก์ชัน
getData()
- สร้างผลลัพธ์ของอินเทอร์เฟซสําหรับการตรวจสอบประเภทข้อมูลหลังจากติดตามที่สังเกตได้
- กําหนดข้อมูลให้กับอาร์เรย์คอมโพเนนต์
กําลังเริ่มต้นอาร์เรย์คอมโพเนนต์
เราจะประกาศและเริ่มอาร์เรย์ของคอมโพเนนต์ภายใน slider.component.ts
ที่เป็นอาร์เรย์ของออบเจ็กต์
วิธีประกาศ
sliderArray: object[];
วิธีเริ่มต้น
constructor(private data: DataService) {
this.sliderArray = [];
}
ถัดไป เราต้องนําเข้าและเริ่มต้นบริการของเราภายในเครื่องมือสร้าง
constructor(private data: DataService) {}
ตอนนี้เราพร้อมจะเริ่มใช้งานบริการของเราและโทรหาบริการจากบริการของเราแล้ว
การรับข้อมูลจากบริการข้อมูล
เพื่อให้ได้ข้อมูลออกจากบริการ เราจะเรียกใช้เมธอด getData()
และสมัครรับข้อมูลที่สังเกตได้ว่าจะส่งคืนกลับมา เราจะสร้างอินเทอร์เฟซ Result,
ด้วย เพื่อที่เราจะพิมพ์กําลังตรวจสอบว่าเราได้รับข้อมูลที่ถูกต้อง
เราจะดําเนินการภายใน ngOnInit
เมธอด:
this.data.getData().subscribe((result: Result)=>{
})
การกําหนดข้อมูลให้กับอาร์เรย์คอมโพเนนต์
ในตอนท้าย เราจะกําหนดข้อมูลให้แก่อาร์เรย์คอมโพเนนต์
this.data.getData().subscribe((result: Result)=>{
this.sliderArray = result.sliderArray;
})
เมื่อเราได้รับข้อมูลภายในอาร์เรย์ของคอมโพเนนต์แล้ว เราจะเชื่อมโยงเทมเพลตของเรากับข้อมูลนี้ได้
ใน slider.component.html,
เรามีเทมเพลต HTML อยู่แล้ว ขั้นตอนถัดไปคือเชื่อมโยงเทมเพลตนี้กับ sliderArray
5 การเชื่อมโยงข้อมูลกับเทมเพลต
เราจะเชื่อมโยงข้อมูลกับเทมเพลตโดยใช้คําสั่ง *ngFor
และสุดท้าย เราจะเพิ่มการเปลี่ยนรูปแบบในเทมเพลตเพื่อให้แถบเลื่อนทํางาน
ซึ่งมี 3 ขั้นตอนดังนี้
- เชื่อมโยง
sliderArray
กับเทมเพลต - การเพิ่มการเชื่อมโยงเหตุการณ์สําหรับปุ่มแถบเลื่อน
- การเพิ่มการเปลี่ยนรูปแบบ CSS โดยใช้
ngStyle
และngClass
การเชื่อมโยงสไลด์ Array กับคอมโพเนนต์
เรามีคอนเทนเนอร์ที่มี img-container
, a
text-container
และ a
slider.
เราจะเชื่อมโยงข้อมูลในคอนเทนเนอร์ทั้ง 3 รายการโดยใช้คําสั่ง *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>
การเชื่อมโยงเหตุการณ์กับ สไลด์Array
เมื่อมีการเชื่อมโยงข้อมูล เราจะเชื่อมโยงเหตุการณ์การคลิกกับปุ่มสไลด์ทุกปุ่มโดยใช้ 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;
}
}
ข้อควรจําที่นี่
- ฟังก์ชันที่ดาวน์เกรดจะลดค่าของพร็อพเพอร์ตี้"เปลี่ยนรูปแบบ"ไป 50 เท่าเมื่อดัชนีที่ส่งผ่านเมื่อคลิกของฟังก์ชัน
selected
- ตรรกะนี้จะแปลงคอนเทนเนอร์ข้อความเป็น 100%, 50%, -50%, -100% ซึ่งส่งผลให้เกิด 4 สถานะที่แตกต่างกัน
การเพิ่มการแปลง CSS โดยใช้ ngStyle & ngClass
ในตอนเริ่มต้น เราตั้งค่ารูปภาพทั้งหมดความทึบแสงเป็น 0 โดยเราจะเพิ่มคลาส selected
โดยใช้ ngClass directive
เมื่อดัชนีที่เลือกเท่ากับดัชนีรูปภาพ คลาส selected
นี้เพิ่มความทึบแสงของ 1 ให้แก่รูปภาพ ซึ่งจะทําให้ผู้ใช้เห็นรูปภาพได้
<div class="img-container" *ngFor="let i of sliderArray; let select = index;"
[ngClass]="{'selected': select == selectedIndex}">
</div>
หลังจากนั้น เราจะแปลคอนเทนเนอร์ข้อความตามค่า 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 การเปลี่ยนคอมโพเนนต์เป็นองค์ประกอบมุมเหลี่ยม
ซึ่งประกอบด้วย 5 ขั้นตอนดังนี้
- การใช้
Shadow DOM
สําหรับองค์ประกอบมุมเหลี่ยม - ใช้ประโยชน์จาก
entryComponents
- กําลังนําเข้าและใช้โมดูล
CreateCustomElement
จาก@angular/elements
- คําจํากัดความเรื่อง
custom-element
- ใช้เมธอด
ngDoBootstrap
การใช้ Shadow DOM สําหรับองค์ประกอบแบบเหลี่ยม
ตอนนี้เราต้องมีแถบเลื่อนรูปภาพ ก็แค่ต้องทําให้เป็น Angular Element
แทน
ส่วนที่สนุกก็คือจะมีการเปลี่ยนแปลงเพียงเล็กน้อยในการสร้าง DOM ของคอมโพเนนต์ซึ่งเป็น Shadow DOM
เราต้องนําเข้าโมดูล ViewEncapsulation
และต้องใช้เมธอด ShadowDom
จากโมดูลดังกล่าว
@Component({
selector: 'app-slider',
templateUrl: './slider.component.html',
styleUrls: ['./slider.component.css'],
encapsulation: ViewEncapsulation.ShadowDom
})
การใช้EntryComponents
คอมโพเนนต์รายการคือคอมโพเนนต์ที่โหลดแบบเหลี่ยมโดยไม่จําเป็น คุณระบุคอมโพเนนต์รายการได้โดยการเปิดเครื่องใน NgModule
เราจะระบุ SliderComponent
ในอาร์เรย์ entryComponents
ภายใน @NgModule
@NgModule({
declarations: [
SliderComponent
],
imports: [
BrowserModule,
HttpClientModule
],
entryComponents: [SliderComponent],
})
การนําเข้าและใช้โมดูล createCustomElement
ในที่นี้จะต้องใช้โมดูล createCustomElement
จาก @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
],
entryComponents: [SliderComponent],
})
export class AppModule {
constructor(private injector: Injector) {
const slider = createCustomElement(SliderComponent, { injector });
customElements.define('motley-slider', slider);
}
ngDoBootstrap() {}
}
การบรรจุองค์ประกอบเชิงมุม
เราจําเป็นต้องแก้ไข 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 display เพื่อแสดง Dist/ โฟลเดอร์ที่สร้างขึ้นโดยใช้คําสั่ง build นอกจากนี้ เรายังใช้ gzip
ที่ได้รับจากคําสั่ง ng package
, แยกออกมา และเผยแพร่เป็น npm module
ได้