如何在angular中实现数据的分段渐进式加载,滚动到页面底部时刷新数据,在app端我们可以用ionic来实现下拉刷新,这里讨论pc端的滚动刷新,我用到了primeNG,primeNG是一个专门为angular设计的UI组件库(链接:https://www.primefaces.org/primeng/#/)。
以下具体讨论实现的步骤:
1.在angular应用中安装该组件
npm install primeng --save (在terminal中运行这个命令)
2.在应用的根模块中导入要用到的primeng模块
3.如果需要用到primeNG的css样式也可以自己在angular-cli.json文件中配置
4.环境搭建好了,现在就可以开始写代码了,下面以我写的demo为例:
创建一个scroll-refresh文件
html页面:
<p-dataScroller [value]="activityLog" [rows]="5" [inline]="true" [lazy]="true" (onLazyLoad)="loadData($event)" scrollHeight="500px"> <p-header> Scroll Down to Load More </p-header> <ng-template let-activityLog pTemplate="item"> <div class="ui-grid ui-grid-responsive ui-fluid" style="font-size:16px;padding:20px;border-bottom:1px solid #D5D5D5"> <div class="ui-grid-row"> <div class="ui-grid-col-3" style="text-align:center"> <img class="responsive" width="120rem" height="130rem" src="assets/showcase/images/1.jpg"> </div> <div class="ui-grid-col-9"> <div class="ui-grid ui-grid-responsive ui-fluid"> <div class="ui-grid-row"> <div class="ui-grid-col-2">编号: </div> <div class="ui-grid-col-10">{{activityLog.ActivityLogId}}</div> </div> <div class="ui-grid-row"> <div class="ui-grid-col-2">内容: </div> <div class="ui-grid-col-10">{{activityLog.Description}}</div> </div> <div class="ui-grid-row"> <div class="ui-grid-col-2">设备: </div> <div class="ui-grid-col-10">{{activityLog.DeviceName}}</div> </div> <div class="ui-grid-row"> <div class="ui-grid-col-2">时间: </div> <div class="ui-grid-col-10">{{activityLog.Time}}</div> </div> </div> </div> </div> </div> </ng-template> </p-dataScroller> <p-dialog header="activityLog Details" [visible]="displayDialog" showEffect="fade" [modal]="true" width="225" (onAfterHide)="onDialogHide()"> <div class="ui-grid ui-grid-responsive ui-fluid" *ngIf="selectedActivityLog" style="font-size:16px;text-align:center;padding:20px"> <div class="ui-grid-row"> <div class="ui-grid-col-12" style="text-align:center"><img src="assets/showcase/images/1.jpg"></div> </div> <div class="ui-grid-row"> <div class="ui-grid-col-4">编号: </div> <div class="ui-grid-col-8">{{selectedActivityLog.ActivityLogId}}</div> </div> <div class="ui-grid-row"> <div class="ui-grid-col-4">内容: </div> <div class="ui-grid-col-8">{{selectedActivityLog.Description}}</div> </div> <div class="ui-grid-row"> <div class="ui-grid-col-4">设备: </div> <div class="ui-grid-col-8">{{selectedActivityLog.DeviceName}}</div> </div> <div class="ui-grid-row"> <div class="ui-grid-col-4">时间: </div> <div class="ui-grid-col-8">{{selectedActivityLog.Time}}</div> </div> </div> </p-dialog>
component部分:
import { Component, OnInit, Injectable } from '@angular/core'; import { Http, Response} from '@angular/http'; import { DataScrollerModule} from 'primeng/primeng'; import { ScrollService } from './scroll.service'; import { ActivityLog } from './scroll.model'; @Component({ selector: 'app-scroll-refresh', templateUrl: './scroll-refresh.component.html', styleUrls: ['./scroll-refresh.component.css'] }) export class ScrollRefreshComponent implements OnInit { activityLog: ActivityLog[]; selectedActivityLog: ActivityLog; displayDialog: boolean; constructor(private personService: ScrollService) { } ngOnInit() { this.personService.getActivities(0, 5).then(person => { this.activityLog = person; }); } selectPerson(person: ActivityLog) { this.selectedActivityLog = person; this.displayDialog = true; } onDialogHide() { this.selectedActivityLog = null; } loadData(event) { console.log('==== lazy load ===='); event.first += 5; event.rows = 5; if (event.first < 50) { console.log(event.first); return this.personService.getActivities(event.first, event.rows).then(person => { console.log(person); person.forEach((val) => { this.activityLog.push(val); }); }); } else { event.first = 0; console.log(event.first); return; } } }
service部分:
import { Injectable } from '@angular/core'; import {Http, Response } from '@angular/http'; import { ActivityLog } from './scroll.model'; import 'rxjs/add/operator/toPromise'; @Injectable() export class ScrollService { constructor(private http: Http) { } getActivities(start: number, end: number) { return this.http.get('http://localhost:52513/api/activitylogs?start=' + start + '&end=' + end) .toPromise() .then(res => { return res.json(); }) .then(data => { return data; }); } }
model部分:
export class ActivityLog { ActivityLogId: string; PatientId: string; Therapist: string; DeviceName: string; Description: string; ActivityId: string; Time: Date; Seconds: number; public constructor( fields?: { ActivityLogId: string; PatientId: string; Therapist: string; DeviceName: string; Description: string; ActivityId: string; Time: Date; Seconds: number }) { if (fields) Object.assign(this, fields); } }
app.module部分:
import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { CommonModule, LocationStrategy, HashLocationStrategy} from '@angular/common'; import { BrowserAnimationsModule} from '@angular/platform-browser/animations'; import { FormsModule, ReactiveFormsModule} from '@angular/forms'; import { HttpModule} from '@angular/http'; // primeNG module import { ScrollService } from './scroll-refresh/scroll.service'; import { MenuItem, AccordionModule, CalendarModule, TabViewModule, CodeHighlighterModule } from 'primeng/primeng'; import { DataScrollerModule} from 'primeng/primeng'; import { DataTableModule} from 'primeng/primeng'; import { DialogModule} from 'primeng/primeng'; // custom primeNG component by myself import { AppComponent } from './app.component'; import { ScrollRefreshComponent } from './scroll-refresh/scroll-refresh.component'; @NgModule({ declarations: [ AppComponent, ScrollRefreshComponent, ], imports: [ BrowserModule, AccordionModule, BrowserAnimationsModule, FormsModule, ReactiveFormsModule, CalendarModule, TabViewModule, CodeHighlighterModule, DataScrollerModule, DataTableModule, DialogModule, HttpModule, ], providers: [ ScrollService, { provide: LocationStrategy, useClass: HashLocationStrategy } ], bootstrap: [ScrollRefreshComponent] }) export class AppModule { }
注: 在app.module文件中我导入了primeNG的很多模块,因为在其他文件中我有用到这些模块,但是如果你只是实现滚动刷新的话,导入对应的模块即可。
angular-cli.json文件:
{ "$schema": "./node_modules/@angular/cli/lib/config/schema.json", "project": { "name": "new-date" }, "apps": [ { "root": "src", "outDir": "dist", "assets": [ "assets", "favicon.ico" ], "index": "index.html", "main": "main.ts", "polyfills": "polyfills.ts", "test": "test.ts", "tsconfig": "tsconfig.app.json", "testTsconfig": "tsconfig.spec.json", "prefix": "app", "styles": [ "styles.css", "../node_modules/primeng/resources/themes/omega/theme.css", "../node_modules/primeng/resources/primeng.min.css" ], "scripts": [], "environmentSource": "environments/environment.ts", "environments": { "dev": "environments/environment.ts", "prod": "environments/environment.prod.ts" } } ], "e2e": { "protractor": { "config": "./protractor.conf.js" } }, "lint": [ { "project": "src/tsconfig.app.json", "exclude": "**/node_modules/**" }, { "project": "src/tsconfig.spec.json", "exclude": "**/node_modules/**" }, { "project": "e2e/tsconfig.e2e.json", "exclude": "**/node_modules/**" } ], "test": { "karma": { "config": "./karma.conf.js" } }, "defaults": { "styleExt": "css", "component": {} } }
需要注意的是,实现分段式加载的关键是每次刷新都只加载一部分数据,即只向数据库中拿取一部分数据而不是一次性全部获取,所以在这方面,必须在后端也要进行配置,前端每次刷新时向后端传递2个参数:start和end,start表示从哪条数据开始获取,end表示一次获取多少条数据,类似于数据的分页展示。
另外,这个demo是一个基于angular-cli实现的用webpack打包的angular应用,一切配置都是在这个前提下完成的,但是如果你的angular应用是基于system.js用gulp打包实现的,那么你的配置方式与我的demo是不相同的。即,在用命令行安装该组件后,还必须在system.js文件中手动进行配置依赖,这里就不多说了,可以参考primeNG官网的例子。