謝謝 Angular User Group的Kevin大大提供的寫作素材。
原文請參考:Component Inheritance in Angular 2
我沒有改變範例,只是想邊翻譯邊操作當做學習筆記,如果有覺得不妥的地方,請再通知我一聲。
有了Component Inheritance的支援,我們可以製作元件的核心功能,
透過繼承去改變樣式及小幅調整功能,就能應付客戶的客製化需求。
先整理一下要如何使用 Angular 2.3 的元件繼承
Metadata(decorators)
像是@Input()、@Output()這類的metadata
子元件可以直接使用或是覆寫自父元件定義的metadata
Constructor:
父元件如果有在Constructor注入Service,子元件可以直接繼承使用。
Lifecycle hooks:
父元件的生命週期方法也會被運作到,就算在子元件中沒有特別定義。
Componet inheritance 不會覆蓋掉父元件的templates及styles,必須做個別的操作。
接下來可以簡單的試用一下Component Inheritance的功能
原文提供的範例是一個pagination的元件。
父元件原本是這樣
繼承之後,希望能改寫成這樣的子元件
因此父元件需要改變以下幾點
使用HyperLink取代Button
把PageCount放在上下頁功能的中間而不是換行
import { Component, Input, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'base-pagination',
template: `
<button (click)="previousPage()" [disabled]="!hasPrevious()">Previous</button>
<button (click)="nextPage()" [disabled]="!hasNext()">Next</button>
<p>page {{ page }} of {{ pageCount }}</p>
`
})
export class BasePaginationComponent {
@Input()
pageCount: number;
@Input()
page: number;
@Output()
pageChanged = new EventEmitter<number>();
nextPage() {
this.page ++;
this.pageChanged.emit(this.page);
}
previousPage() {
this.page --;
this.pageChanged.emit(this.page);
}
hasPrevious(): boolean { return +this.page > 1; }
hasNext(): boolean { return +this.page < +this.pageCount; }
}
父元件的程式碼有幾個重點
我們接受二個input變數
page 用來代表現在頁數
pageCount 用來代表全部頁數
當頁數改變時,會emit PageChanged envent
如果 previous 或 next button達到最小或最大頁數則Disable。
// custom-pagination.component.ts
import { Component } from '@angular/core';
import { BasePaginationComponent } from './base-pagination.component';
@Component({
selector: 'custom-pagination',
template: `
<a (click)="previousPage()" [class.disabled]="!hasPrevious()"
href="javascript:void(0)">
««
</a>
<span>{{ page }} / {{ pageCount }}</span>
<a (click)="nextPage()" [class.disabled]="!hasNext()"
href="javascript:void(0)" >
»»
</a>
`
})
export class CustomPaginationComponent extends BasePaginationComponent {
}
子元件的程式碼的重點如下
首先要import BasePaginationComponent
然後使用 extend 繼承 BasePaginationComponent
修改Template,把Button改成Hyperlink
修改Template,把頁數資訊改到上下頁的中間
我們可以reuse所有從父元件繼承下來的inputs、outputs、properties及function
在父元件增加二個Input-previousText、nextText,用來標示上一頁/下一頁按鈕的文字,並且在沒有指定文字時給予預設值。
// base-pagination.component.ts
@Component({
selector: 'base-pagination',
template: `
<button (click)="previousPage()" [disabled]="!hasPrevious()">{{ previousText }}</button>
<button (click)="nextPage()" [disabled]="!hasNext()">{{ nextText }}</button>
<p>page {{ page }} of {{ pageCount }}</p>
`
})
export class BasePaginationComponent {
...
@Input()
previousText = 'Previous';
@Input()
nextText = 'Next';
...
}
接下來我們在子元件,覆寫繼承自父元件的Input-previousText、nextText,重新設定初值為符號<<
及>>
// custom-pagination.component.ts
import { Component, Input } from '@angular/core';
import { BasePaginationComponent } from './base-pagination.component';
@Component({
selector: 'custom-pagination',
template: `
<a (click)="previousPage()" [class.disabled]="!hasPrevious()"
href="javascript:void(0)">
{{ previousText }}
</a>
<span>{{ page }} / {{ pageCount }}</span>
<a (click)="nextPage()" [class.disabled]="!hasNext()"
href="javascript:void(0)" >
{{ nextText }}
</a>
`
})
export class CustomPaginationComponent extends BasePaginationComponent {
@Input()
previousText = '<<'; // 覆寫預設值
@Input()
nextText = '>>'; // 覆寫預設值
...
}
在子元件建立一個父元件沒有的title
property
// custom-pagination.component.ts
@Component({
selector: 'custom-pagination',
template: `
<h2>{{ title }}</h2>
<a (click)="previousPage()" [class.disabled]="!hasPrevious()"
href="javascript:void(0)">
{{ previousText }}
</a>
<span>{{ page }} / {{ pageCount }}</span>
<a (click)="nextPage()" [class.disabled]="!hasNext()"
href="javascript:void(0)" >
{{ nextText }}
</a>
`
})
export class CustomPaginationComponent extends BasePaginationComponent {
@Input()
title: string; // title input只有子元件才有
...
}
完整的程式碼,可以參考原文作者提供的程式碼範例