-
Notifications
You must be signed in to change notification settings - Fork 4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor(module:list): refactor list (#2548)
* refactor(module:list): refactor list * fix: import scrolling in share module * chore: add encapsulation:ViewEncapsulation.None ref #2381
- Loading branch information
Showing
12 changed files
with
200 additions
and
213 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,18 @@ | ||
--- | ||
order: 6 | ||
title: | ||
zh-CN: 滚动加载 | ||
en-US: Scrolling loaded | ||
zh-CN: 滚动加载无限长列表 | ||
en-US: Infinite & virtualized | ||
--- | ||
|
||
## zh-CN | ||
|
||
结合 [ngx-infinite-scroll](https://github.com/orizens/ngx-infinite-scroll) 实现滚动自动加载列表。 | ||
结合 [cdk-virtual-scroll](https://material.angular.io/cdk/scrolling/overview) 实现滚动加载无限长列表,带有虚拟化 virtualization 功能,能够提高数据量大时候长列表的性能。 | ||
|
||
`Virtualized` 是在大数据列表中应用的一种技术,主要是为了减少不可见区域不必要的渲染从而提高性能,特别是数据量在成千上万条效果尤为明显。 | ||
|
||
## en-US | ||
|
||
The example of infinite load with [ngx-infinite-scroll](https://github.com/orizens/ngx-infinite-scroll). | ||
An example of infinite list & virtualized loading using [cdk-virtual-scroll](https://material.angular.io/cdk/scrolling/overview). | ||
|
||
`Virtualized` rendering is a technique to mount big sets of data. It reduces the amount of rendered DOM nodes by tracking and hiding whatever isn't currently visible. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,78 +1,108 @@ | ||
// tslint:disable:no-any | ||
import { CollectionViewer, DataSource } from '@angular/cdk/collections'; | ||
import { HttpClient } from '@angular/common/http'; | ||
import { Component, OnInit } from '@angular/core'; | ||
import { NzMessageService } from 'ng-zorro-antd'; | ||
|
||
const fakeDataUrl = 'https://randomuser.me/api/?results=5&inc=name,gender,email,nat&noinfo'; | ||
import { ChangeDetectionStrategy, Component } from '@angular/core'; | ||
import { BehaviorSubject, Observable, Subscription } from 'rxjs'; | ||
|
||
@Component({ | ||
selector: 'nz-demo-list-infinite-load', | ||
template: ` | ||
<!--<div class="demo-infinite-container"--> | ||
<!--infiniteScroll--> | ||
<!--[infiniteScrollDistance]="2"--> | ||
<!--[infiniteScrollThrottle]="50"--> | ||
<!--(scrolled)="onScroll()"--> | ||
<!--[scrollWindow]="false">--> | ||
<!--<nz-list [nzDataSource]="data" [nzRenderItem]="item">--> | ||
<!--<ng-template #item let-item>--> | ||
<!--<nz-list-item>--> | ||
<!--<nz-list-item-meta--> | ||
<!--[nzTitle]="nzTitle"--> | ||
<!--nzAvatar="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png"--> | ||
<!--[nzDescription]="item.email">--> | ||
<!--<ng-template #nzTitle>--> | ||
<!--<a href="https://ng.ant.design">{{item.name.last}}</a>--> | ||
<!--</ng-template>--> | ||
<!--</nz-list-item-meta>--> | ||
<!--</nz-list-item>--> | ||
<!--</ng-template>--> | ||
<!--<nz-spin *ngIf="loading && hasMore" class="demo-loading"></nz-spin>--> | ||
<!--</nz-list>--> | ||
<!--</div>--> | ||
<div> | ||
<cdk-virtual-scroll-viewport | ||
itemSize="73" | ||
class="demo-infinite-container" | ||
> | ||
<nz-list> | ||
<nz-list-item *cdkVirtualFor="let item of ds"> | ||
<nz-skeleton | ||
*ngIf="!item" | ||
[nzAvatar]="true" | ||
[nzParagraph]="{ rows: 1 }" | ||
></nz-skeleton> | ||
<nz-list-item-meta | ||
*ngIf="item" | ||
[nzTitle]="nzTitle" | ||
nzAvatar="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" | ||
[nzDescription]="item.email" | ||
> | ||
<ng-template #nzTitle> | ||
<a href="https://ng.ant.design">{{item.name.last}}</a> | ||
</ng-template> | ||
</nz-list-item-meta> | ||
</nz-list-item> | ||
</nz-list> | ||
</cdk-virtual-scroll-viewport> | ||
</div> | ||
`, | ||
styles: [ ` | ||
:host ::ng-deep .demo-infinite-container { | ||
border: 1px solid #e8e8e8; | ||
border-radius: 4px; | ||
overflow: auto; | ||
padding: 8px 24px; | ||
height: 300px; | ||
} | ||
:host ::ng-deep .demo-loading { | ||
position: absolute; | ||
bottom: -40px; | ||
left: 50%; | ||
} | ||
` ] | ||
styles: [ | ||
` | ||
:host ::ng-deep .demo-infinite-container { | ||
height: 300px; | ||
border: 1px solid #e8e8e8; | ||
border-radius: 4px; | ||
} | ||
` | ||
], | ||
changeDetection: ChangeDetectionStrategy.OnPush | ||
}) | ||
export class NzDemoListInfiniteLoadComponent implements OnInit { | ||
data: any[] = []; | ||
loading = false; | ||
hasMore = true; | ||
export class NzDemoListInfiniteLoadComponent { | ||
ds = new MyDataSource(this.http); | ||
|
||
constructor(private http: HttpClient) {} | ||
} | ||
|
||
constructor(private http: HttpClient, private msg: NzMessageService) {} | ||
class MyDataSource extends DataSource<string | undefined> { | ||
private length = 100000; | ||
private pageSize = 10; | ||
private cachedData = Array.from<any>({ length: this.length }); | ||
private fetchedPages = new Set<number>(); | ||
private dataStream = new BehaviorSubject<any[]>(this.cachedData); | ||
private subscription = new Subscription(); | ||
|
||
ngOnInit(): void { | ||
this.getData((res: any) => this.data = res.results); | ||
constructor(private http: HttpClient) { | ||
super(); | ||
} | ||
|
||
getData(callback: (res: any) => void): void { | ||
this.http.get(fakeDataUrl).subscribe((res: any) => callback(res)); | ||
connect(collectionViewer: CollectionViewer): Observable<any[]> { | ||
this.subscription.add( | ||
collectionViewer.viewChange.subscribe(range => { | ||
const startPage = this.getPageForIndex(range.start); | ||
const endPage = this.getPageForIndex(range.end - 1); | ||
for (let i = startPage; i <= endPage; i++) { | ||
this.fetchPage(i); | ||
} | ||
}) | ||
); | ||
return this.dataStream; | ||
} | ||
|
||
onScroll(): void { | ||
if (this.loading) return; | ||
this.loading = true; | ||
if (this.data.length > 14) { | ||
this.msg.warning('Infinite List loaded all'); | ||
this.hasMore = false; | ||
this.loading = false; | ||
disconnect(): void { | ||
this.subscription.unsubscribe(); | ||
} | ||
|
||
private getPageForIndex(index: number): number { | ||
return Math.floor(index / this.pageSize); | ||
} | ||
|
||
private fetchPage(page: number): void { | ||
if (this.fetchedPages.has(page)) { | ||
return; | ||
} | ||
this.getData((res: any) => { | ||
this.data = this.data.concat(res.results); | ||
this.loading = false; | ||
}); | ||
this.fetchedPages.add(page); | ||
|
||
this.http | ||
.get( | ||
`https://randomuser.me/api/?results=${ | ||
this.pageSize | ||
}&inc=name,gender,email,nat&noinfo` | ||
) | ||
.subscribe((res: any) => { | ||
this.cachedData.splice( | ||
page * this.pageSize, | ||
this.pageSize, | ||
...res.results | ||
); | ||
this.dataStream.next(this.cachedData); | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,13 @@ | ||
<div *ngIf="isAvatar" class="ant-list-item-meta-avatar"> | ||
<div *ngIf="avatarStr || avatarTpl" class="ant-list-item-meta-avatar"> | ||
<ng-container *ngIf="avatarStr; else avatarTpl"> | ||
<nz-avatar [nzSrc]="avatarStr"></nz-avatar> | ||
</ng-container> | ||
</div> | ||
<div *ngIf="isTitle || isDesc" class="ant-list-item-meta-content"> | ||
<h4 *ngIf="isTitle" class="ant-list-item-meta-title"> | ||
<ng-container *ngIf="titleStr; else titleTpl">{{ titleStr }}</ng-container> | ||
<div *ngIf="nzTitle || nzDescription" class="ant-list-item-meta-content"> | ||
<h4 *ngIf="nzTitle" class="ant-list-item-meta-title"> | ||
<ng-container *nzStringTemplateOutlet="nzTitle">{{ nzTitle }}</ng-container> | ||
</h4> | ||
<div *ngIf="isDesc" class="ant-list-item-meta-description"> | ||
<ng-container *ngIf="descStr; else descTpl">{{ descStr }}</ng-container> | ||
<div *ngIf="nzDescription" class="ant-list-item-meta-description"> | ||
<ng-container *nzStringTemplateOutlet="nzDescription">{{ nzDescription }}</ng-container> | ||
</div> | ||
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.