iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 24
2
Modern Web

Angular 元件庫 NG-ZORRO 基礎入門系列 第 24

[Angular 元件庫 NG-ZORRO 基礎入門] Day 24 - 原始碼初窺: Input

  • 分享至 

  • xImage
  •  

前言回顧

我們昨天已經瞭解了 NG-ZORRO 專案的基本結構,也介紹了一些核心檔案資訊,今天我們來探索一下 NG-ZORRO 元件設計裡的一些設計方法。

元件

開發之前

我們都知道,開發一個元件絕不是簡單的程式碼堆砌,我們要對元件進行充分分析,包括功能分析、質量保證、文件說明、國際化、維護擴充套件等。
我們今天就以 Input 元件來介紹一下如何從開發到釋出的過程。

Input 元件

作為頁面開發中最常用的元件,我們在多種場景中都會使用得到。

功能分析

我們先來看一下 html 原生輸入框 input 的例子:

<input type="text" name="name" placeholder="this is an input." />

我們查閱 MDN 介紹文件也發現 input 元素包含了非常多的屬性供我們使用。不知道大家是否還記得我們專案剛開始時介紹 button 元件設計模式時,為什麼不採用 component 包裹的形式開發,例如這樣在 Angular 中實現 input 元件:

@Component({
  selector: 'nz-input',
  template: '<input xxx="xxx" />',
})
export class NzInputComponent {
	@Input() type: string;
	...
}

很明顯,這種方式極大地限制了我們對 input 元素的使用和拓展,比如我們如果想未來支援 無障礙 閱讀,就會無從下手。

那麼是否可以使用 ng-content 來投射渲染使用者手動輸入的元素呢?比如這樣設計:

@Component({
  selector: 'nz-input',
  template: '<span #inputElement><ng-content></ng-content></span>',
})
export class NzInputComponent {
    @ViewChild('inputElement', { static: true }) contentElement: ElementRef;
	@Input() property: propertyType;
	// do something to deal with inputElement
}

這時我們可以這樣使用 input 元件:

<nz-input [nzProperty]="propertyValue">
  <input type="text" name="name" placeholder="this is an input." />
</nz-input>

將使用者的 input 元素渲染,nz-input 只作為增強屬性,比如新增主題色、樣式等。這種方式似乎已經滿足我們的需求了,但是每次只是使用 input 元素就得 nz-input 包裹就顯得太冗餘了,於是 Directive 指令成為了更適合的選擇。

程式碼實現

@Directive({
  selector: '[nz-input]',
  exportAs: 'nzInput',
  host: {
    '[class.ant-input-disabled]': 'disabled',
    '[class.ant-input-lg]': `nzSize === 'large'`,
    '[class.ant-input-sm]': `nzSize === 'small'`
  }
})
export class NzInputDirective {
  @Input() nzSize: NzSizeLDSType = 'default';
  @Input() @InputBoolean() disabled = false;

  constructor(renderer: Renderer2, elementRef: ElementRef) {
    renderer.addClass(elementRef.nativeElement, 'ant-input');
  }
}

這就是 NG-ZORRO 的 input 指令元件,接受了大小、禁用屬性來增強 input 元素。非常簡單的程式碼實現,在設計中如果是對已有的 html 元素進行增強,儘量要做到非侵入,讓使用者有更多的操作權,不能取小舍大。

同樣的,nz-autosize.directive.ts 針對文字域多行輸入也遵循了此設計理念。

nz-input-group

但是有時候我們需要對實現如下功能:
https://img.alicdn.com/tfs/TB1YUdbhkL0gK0jSZFtXXXQCXXa-804-82.jpg

<nz-input-group [nzSuffix]="suffixTemplate" [nzPrefix]="prefixTemplate">
  <input type="text" nz-input placeholder="Enter your username" />
</nz-input-group>
<ng-template #prefixTemplate><i nz-icon nzType="user"></i></ng-template>
<ng-template #suffixTemplate
			 ><i nz-icon nz-tooltip nzTitle="Extra information" nzType="info-circle"></i
  ></ng-template>

這對 input 進行深度定製,簡單的指令已無法滿足了,這時我們就可以使用上述說過的 ng-content 方法來增強,看一下 nz-input-group 程式碼,我們發現其設計都用了 ng-content 渲染使用者資料,在外部增加自有增強屬性,如支援字首字尾的程式碼:

<span class="ant-input-affix-wrapper" [class.ant-input-affix-wrapper-sm]="isSmall" [class.ant-input-affix-wrapper-lg]="isLarge" *ngIf="isAffix">
  <ng-template *ngTemplateOutlet="affixTemplate"></ng-template>
</span>
<!--前後綴模板-->
<ng-template #affixTemplate>
  <!--字首-->
  <span class="ant-input-prefix" *ngIf="nzPrefix || nzPrefixIcon">
    <!-- TODO: should have a class to set its color, cc: antd-->
    <i nz-icon [nzType]="nzPrefixIcon" *ngIf="nzPrefixIcon" style="color: rgba(0, 0, 0, 0.25)"></i>
    <ng-container *nzStringTemplateOutlet="nzPrefix">{{ nzPrefix }}</ng-container>
  </span>
  <!--渲染使用者元素-->
  <ng-template *ngTemplateOutlet="contentTemplate"></ng-template>
  <!--字尾-->
  <span class="ant-input-suffix" *ngIf="nzSuffix || nzSuffixIcon">
    <i nz-icon [nzType]="nzSuffixIcon" *ngIf="nzSuffixIcon"></i>
    <ng-container *nzStringTemplateOutlet="nzSuffix">{{ nzSuffix }}</ng-container>
  </span>
</ng-template>
<!--使用者輸入元素-->
<ng-template #contentTemplate>
  <ng-content></ng-content>
</ng-template>

這樣我們即可以對使用者元素進行保留,也能在此基礎上渲染我們需要新增的屬性。

測試驗證

因為是開源元件,所以我們必須要建立一個測試檔案來測試我們支援的全部屬性,Angular 測試 內容可在官方網站查閱到。目前元件庫的測試覆蓋率達到 92%+,我們在設計元件時(如果是通用性元件,非業務元件),最好形成良好的測試習慣,保證元件可用性。

總結 & 預告

今天我們介紹了 input 元件的原始碼,主要注意的是 directive 指令和 ng-content 的使用,在設計元件時大家也需要權衡哪種方式是最適合自己的。

相關資料

  • Angular 測試:https://angular.cn/guide/testing
  • Directive:https://angular.cn/api/core/Directive

上一篇
[Angular 元件庫 NG-ZORRO 基礎入門] Day 23 - 原始碼初窺: 專案結構
下一篇
[Angular 元件庫 NG-ZORRO 基礎入門] Day 25 - 原始碼初窺: Select
系列文
Angular 元件庫 NG-ZORRO 基礎入門30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言