使用 Angular 建構圖片滑桿元素

1. 簡介

作者:Aayush Arora

Angular 元素是封裝成自訂元素的 Angular 元件。這項功能目前由 Chrome、Opera 和 Safari 支援,可透過其他瀏覽器使用 Polyfill。這些元件可以運用整個角度的基礎架構,搭配常見的角度介面與變更偵測策略。完成註冊後,即可在瀏覽器中使用這些元素。

此程式碼研究室將逐步引導您建立您自己的圖像滑行式元件元件,然後協助您將其轉換為有角元件,如此即可在 Angular 架構外運作。

建構目標

在本程式碼研究室中,您將使用角度建構圖片滑桿元素。您的元素:

  • 就像在瀏覽器中使用 HTML 元素一樣
  • 可插入任何與 DOM 通訊的架構。

您將會瞭解的內容

  • 如何建立圖片滑桿自訂元件
  • 如何將圖片滑桿自訂元件轉換為自訂元素
  • 如何封裝元件,讓元件在瀏覽器中運作

軟硬體需求

本程式碼研究室聚焦於 Angular 元素。內含不相關的概念和程式碼區塊會重疊在外,可供您直接複製並貼上。

2. 開始設定

下載程式碼

點選下方連結即可下載這個程式碼研究室的所有程式碼:

將下載的 ZIP 檔案解壓縮。這會將 (angular-element-codelab-master) 的根目錄解壓縮,其中包含

(image-slider)(image-slider-finished)兩個資料夾。我們會透過名為圖片滑塊的目錄執行所有程式設計工作。

執行專案

如要執行專案,請從根目錄 ( image-slider ) 執行指令 ( ng-serve )。

應用程式啟動後,您便能查看下列資訊:

19ffd082e2f024a5.png

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」繫結至範本
  • 新增滑桿按鈕的事件繫結
  • 使用 ngStylengClass 新增 CSS 轉換

將 slArrayArray 與元件繫結

我們有一個容器內含 img-containera text-containera 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