排序、分页、过滤、自定义操做列、列表中根据数据展现相应图标、跳转详情页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();
});
}
}
复制代码
经过继承一些列表组件或者基类,能够大大地提高组件功能的复用率,而且可以提升开发效率。在一些业务场景中,咱们总会面临着,多处同样的代码,若是有变更,就要所有更改,这样不利于代码的简洁,并且代码逻辑相对单一。由此咱们要学会封装一些经常使用性的组件,来达到代码的复用率,增强代码的健壮性。