程式碼研究室簡介
1. 引言
作者:Aayush Arora
Angular 元素是封裝成自訂元素的 Angular 元件。這項功能目前由 Chrome、Opera 和 Safari 支援,可透過其他瀏覽器使用 Polyfill。這些元件可以運用整個角度的基礎架構,搭配常見的角度介面與變更偵測策略。完成註冊後,即可在瀏覽器中使用這些元素。
此程式碼研究室將逐步引導您建立您自己的圖像滑行式元件元件,然後協助您將其轉換為有角元件,如此即可在 Angular 架構外運作。
建構目標
在本程式碼研究室中,您將使用角度建構圖片滑桿元素。您的元素:
|
您將會瞭解的內容
- 如何建立圖片滑桿自訂元件
- 如何將圖片滑桿自訂元件轉換為自訂元素
- 如何封裝元件,讓元件在瀏覽器中運作
軟硬體需求
- 最新版本的 angular-cli。
- 範例程式碼
- 文字編輯器
- 角度元件元件基本知識
本程式碼研究室聚焦於 Angular 元素。內含不相關的概念和程式碼區塊會重疊在外,可供您直接複製並貼上。
2. 開始設定
下載程式碼
點選下方連結即可下載這個程式碼研究室的所有程式碼:
將下載的 ZIP 檔案解壓縮。這會將 (angular-element-codelab-master)
的根目錄解壓縮,其中包含
(image-slider)
和(image-slider-finished)
兩個資料夾。我們會透過名為圖片滑塊的目錄執行所有程式設計工作。
執行專案
如要執行專案,請從根目錄 ( image-slider ) 執行指令 ( ng-serve )。
應用程式啟動後,您便能查看下列資訊:
3. 要製作圖片滑桿自訂元件嗎?
如何建立圖片滑桿?
在這個圖片滑桿上,使用角度點擊繫結的繫結按鈕。我們將建立含有圖片、替代標記、連結等物件的陣列。我們會將這些圖片彼此放入容器下方,並在使用者點擊時翻譯容器。
我們要建立一個圖像滑塊元件,然後將該元件轉換成有角度的元素。
- 圖片和標題的容器。
- 包含資料的陣列
- 可繫結資料的範本
4. 實作圖片滑桿元件
有很多方法可以開始使用任何專案,在這種情況下,為了簡化專案並集中使用 Angular 元素,我們為您提供基本程式碼和 css。
建立陣列和資料服務
請記住,滑桿 Array 將包含:
- 滑桿上的圖片網址的 img 鍵
- 為圖片提供 alt 標記的 alt 標記
- 用來提供圖片說明的文字
src/assets
目錄中的 data.json
檔案看起來應該會像這樣。
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
檔案,我們會使用 @angular/common/http
中的 httpClient
模組編寫 getData()
方法,以從上方建立的陣列中擷取資料。
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
取得物件
我們必須執行三個步驟:
- 初始化元件陣列
- 訂閱
getData()
函式傳回的「可觀察」 - 建立介面 Result,以便在訂閱可觀測資料後檢查類型。
- 將資料指派給元件陣列。
初始化元件陣列
我們將宣告並初始化 slider.component.ts
中的元件陣列,該物件為物件陣列:
宣告:
sliderArray: object[];
如何初始化:
constructor(private data: DataService) {
this.sliderArray = [];
}
接著我們需要在建構函式內匯入並初始化服務
constructor(private data: DataService) {}
現在,您可以開始使用我們的服務,並且呼叫我們的服務方法。
從 Data Service 取得資料
為了從服務中取得資料,我們會呼叫 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
指令,將資料繫結至範本,最後也會在範本中加入轉換,讓滑桿正常運作。
其中包含三個步驟:
- 將「
sliderArray
」繫結至範本 - 新增滑桿按鈕的事件繫結
- 使用
ngStyle
和ngClass
新增 CSS 轉換
將 slArrayArray 與元件繫結
我們有一個容器內含 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>
將事件繫結至 slArray
資料繫結後,我們將使用 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%,得到四個不同的狀態。
使用 ngStyle & ngClass 新增 CSS 轉換
一開始,我們將所有圖片的透明度設為 0,在所選索引變成圖片索引時,使用 ngClass directive
新增 selected
類別。這個 selected
類別會在圖片中加入不透明度,讓使用者能夠看見圖片。
<div class="img-container" *ngFor="let i of sliderArray; let select = index;"
[ngClass]="{'selected': select == selectedIndex}">
</div>
完成後,我們會根據 select()
函式計算的 transform
值,對文字容器進行翻譯。
<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. 將元件轉換成角形元素
這個程序包含五個步驟:
- 使用
Shadow DOM
做為有角元素 - 使用
entryComponents
- 匯入並使用
@angular/elements
中的CreateCustomElement
模組 - 定義
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 中啟動元件元件。
這裡的「@NgModule
」陣列會在 entryComponents
陣列中指定「SliderComponent
」
@NgModule({
declarations: [
SliderComponent
],
imports: [
BrowserModule,
HttpClientModule
],
entryComponents: [SliderComponent],
})
匯入及使用 createCustomElement 模組
這裡我們需要使用 @angular/elements.
中的 createCustomElement
模組。您必須使用 SliderComponent,
做為 createCustomElement
函式的參數。操作完成後,我們必須在 DOM 中註冊 slider
。
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 放送」來提供使用 build 指令產生的 Dist/ 資料夾。此外,我們也可以使用從 ng package
指令取得的 gzip
,加以擷取並發布為 npm module
。