排序、分頁、過濾、自定義操做列、列表中根據數據展現相應圖標、跳轉詳情頁html
封裝一個列表基類,派生類繼承該類,複用基類的功能。git
若是派生類未聲明構造函數,它將使用基類的構造函數。這意味着在基類構造函數注入的全部服務,子組件都能訪問到。github
若是基類中包含生命週期鉤子,如 ngOnInit
、ngOnChanges
等,而在派生類沒有定義相應的生命週期鉤子,基類的生命週期鉤子會被自動調用。若是須要在派生類觸發ngOnInit
,則須要在派生類上定義相應的生命週期鉤子。編程
派生類不能訪問私有方法和屬性,僅繼承公共方法和屬性。api
模板是不能被繼承的 ,派生類需自定義模板,所以共享的 DOM 結構或行爲須要單獨處理。bash
裝飾器和元數據(@Component
,@Directive
,@NgModule
等),這些元數據和裝飾器不會被派生類繼承,可是有一個例外,@Input
和@Output
裝飾器會傳遞給派生類app
派生類必須經過調用super注入基類的參數異步
application列表組件和基類ResourceListBase
、ResourceListWithStatuses
關係異步編程
application列表組件主要繼承父類ResourceListWithStatuses
,經過重寫ResourceListWithStatuses
的方法,自定義模板,來複用父類的功能屬性。函數
@Component({
selector: 'sym-application-list',
templateUrl: './application.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
})
複製代碼
經過expends繼承父類
經過繼承基類ResourceListWithStatuses
,能夠複用其基本的功能屬性,同時能夠定義屬性和方法擴展列表組件的功能,實現這個列表組件主要的是若是調用組件方法發起請求,獲取到數據
重寫getResourceObservable
方法,該方法主要是返回一個Observable,進行異步編程。
在這個方法裏,能夠請求多個api,使用Observable.forkJoin,能夠合併多個Observable,返回一個Observable。
結合sym-select
組件搜索
sym-select
組件的namespace下拉列表的數據nsList是異步獲取的,若是是選擇是的namespace是ALL,那麼列表組件要獲取到nsList,而後對每一個nsList裏的namespace進行所有請求。若是選擇的是某個namesapce,那麼就傳入namespace的值,進行單個請求
這裏也是比較疑惑的地方,以前想經過@Input
傳入屬性的方式,來把搜索組件的數據傳遞給applicaiton列表組件sym-application-list
可是嘗試以後,發如今頁面初始化的時候,經過@Input
的屬性傳入的nsList
爲空的。若是傳入的屬性是同步獲取的,則能夠傳遞到application列表組件中
最後獲取搜索參數的方式,採起服務依賴注入的方式來獲取。
ngOnInit() {
this.data_.sortingDataAccessor = (item, property) => {
switch (property) {
case 'name': return item.objectMeta.name;
case 'creationTimestamp': return item.status.creationTimestamp;
case 'namespace': return item.objectMeta.namespace;
default: return item[property];
}
};
}
getResourceObservable(params?: HttpParams): Observable<ApplicationList> {
const res = this.localtionService_.onNamespaceUpdate.subscribe(() => {
this.namespace = this.localtionService_.current().namespace;
this.nsList = this.localtionService_.current().namespaceList;
});
const data: any = {
items: [],
listMeta: {
totalItems: 0
}
};
if (this.namespace === 'ALL') {
const list = this.nsList.slice(1);
const observableList = list.map((ns: any) => {
return this.application_.get(this.endpoint, undefined, ns.name);
});
if (observableList && observableList.length === 0) {
return new Observable((observer) => {
observer.next(data);
});
}
return new Observable((observer) => {
Observable.forkJoin(observableList).subscribe((res: any) => {
res.map((item: any, index: number) => {
item.items = item.items.map((v: any) => {
v.objectMeta.namespace = list[index].name;
return v;
});
data.items = data.items.concat(item.items);
data.listMeta.totalItems += item.listMeta.totalItems;
});
observer.next(data);
});
});
} else if (this.namespace !== undefined) {
return this.application_.get(this.endpoint, undefined, this.namespace, params);
}
return new Observable((observer) => {
observer.next(data);
});
}
map(applicationList: ApplicationList): Application[] {
if (this.namespace !== 'ALL') {
applicationList.items = applicationList.items.map((v: any) => {
v.objectMeta.namespace = this.namespace;
return v;
});
}
console.log('applicationList', applicationList);
return applicationList.items;
}
isInErrorState(resource: Application): boolean {
return resource.status ? (resource.status.replicas && resource.status.replicas !== resource.status.availableReplicas ?
true : false) : false;
}
isInSuccessState(resource: Application): boolean {
return resource.status ? (resource.status.replicas && resource.status.replicas === resource.status.availableReplicas ?
true : false) : false;
}
protected getDisplayColumns(): string[] {
return ['statusicon', 'name', 'namespace', 'labels', 'replicas', 'creationTimestamp'];
}
複製代碼
<sym-application-list #applicationList></sym-application-list>
複製代碼
初始化時,調用getList請求方法
this.applicationList.getList();
複製代碼
在基類中已有聲明註冊操做列的方法,在application列表組件繼承該方法,在構造函數中,註冊操做列,MenuComponent
是引入的組件
this.registerActionColumn<MenuComponent>('menu', MenuComponent);
複製代碼
這裏的Pods列表組件也是繼承了ResourceListWithStatuses
繼承的組件都會繼承過濾功能,由於繼承的組件的模板是自定義的,能夠在模板上引入過濾的組件
<kd-card-list-filter></kd-card-list-filter>
複製代碼
基類中以判斷是否有過濾組件,並訂閱過濾組件的方法觸發列表過濾
ngAfterViewInit(): void {
this.data_.sort = this.matSort_;
this.data_.paginator = this.matPaginator_;
if (this.cardFilter_) {
// 表格搜索
this.cardFilter_.filterEvent.subscribe(() => {
const filterValue = this.cardFilter_.query;
this.data_.filter = filterValue.trim().toLowerCase();
});
}
}
複製代碼
經過繼承一些列表組件或者基類,能夠大大地提高組件功能的複用率,而且可以提升開發效率。在一些業務場景中,咱們總會面臨着,多處同樣的代碼,若是有變更,就要所有更改,這樣不利於代碼的簡潔,並且代碼邏輯相對單一。由此咱們要學會封裝一些經常使用性的組件,來達到代碼的複用率,增強代碼的健壯性。