Angular Ionic2变更检测问题,忽略第一个变更
我正在用ionic2开发一个测验应用程序。这些问题从数据库中提取,并使用Angular Ionic2变更检测问题,忽略第一个变更,angular,ionic2,rxjs,observable,Angular,Ionic2,Rxjs,Observable,我正在用ionic2开发一个测验应用程序。这些问题从数据库中提取,并使用-组件显示。模板的重要部分如下所示: <ion-content padding> ... <ion-slides *ngIf="status === QuizState.running" pager="true" paginationType="progress"> <ion-slide *ngFor="let question of questions; let index =
-组件显示。模板的重要部分如下所示:
<ion-content padding>
...
<ion-slides *ngIf="status === QuizState.running" pager="true" paginationType="progress">
<ion-slide *ngFor="let question of questions; let index = index">
<span>{{ question|json}}</span>
...
</ion-slide>
</ion-slides>
...
</ion-content>
import { Component, ViewChild, ChangeDetectionStrategy } from '@angular/core';
import { NavController, Slides } from 'ionic-angular';
import { QuizLoaderService, QuizType, QuizDefinition } from '../../components/quiz-item/quiz-loader.service';
import { SamplePipe } from 'ngx-pipes/src/app/pipes/array/sample';
import { ShufflePipe } from 'ngx-pipes/src/app/pipes/array/shuffle';
import { Observable } from 'rxjs';
import 'rxjs/add/observable/from';
import 'rxjs/add/observable/forkJoin';
enum QuizState {
idle,
running,
finished
}
@Component({
selector: 'page-quiz',
templateUrl: 'quiz.html',
providers: [
SamplePipe, ShufflePipe, QuizLoaderService
],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class QuizPage {
private slides: Slides;
private status: QuizState = QuizState.idle;
private questions: Array<QuizType|QuizDefinition> = [];
private readonly numberOfQuestions = 10;
// make enum accessable from the view
readonly QuizState = QuizState;
constructor(public navCtrl: NavController, private quizLoaderService: QuizLoaderService) {}
@ViewChild(Slides) set slidesViewChild(slides: Slides) {
if(slides) {
slides.onlyExternal = true;
slides.ionSlideWillChange.subscribe(slides => {
// load the after next question in advance
if(!slides.isEnd()) {
let index: number = slides.getActiveIndex() + 1;
let quizType: QuizType = <QuizType>this.questions[index];
this.quizLoaderService.loadQuizItem(quizType).subscribe((item: QuizDefinition) => this.questions[index] = item);
}
});
}
this.slides = slides;
}
startQuiz() {
this.status = QuizState.running;
// generate an array of question types
this.questions = this.quizLoaderService.getQuizItems(this.numberOfQuestions);
// fetch data for the first two questions
let startingQuestions: Observable<QuizDefinition>[] = [0, 1].map(index => {
let quizType = <QuizType>this.questions[index];
return this.quizLoaderService.loadQuizItem(quizType);
});
Observable.forkJoin(startingQuestions).subscribe(
// update first two items with actual question data
(items: QuizDefinition[]) => this.questions.splice(0, items.length, ...items)
);
}
...
}
...
{{问题| json}}
...
...
组件代码如下所示:
<ion-content padding>
...
<ion-slides *ngIf="status === QuizState.running" pager="true" paginationType="progress">
<ion-slide *ngFor="let question of questions; let index = index">
<span>{{ question|json}}</span>
...
</ion-slide>
</ion-slides>
...
</ion-content>
import { Component, ViewChild, ChangeDetectionStrategy } from '@angular/core';
import { NavController, Slides } from 'ionic-angular';
import { QuizLoaderService, QuizType, QuizDefinition } from '../../components/quiz-item/quiz-loader.service';
import { SamplePipe } from 'ngx-pipes/src/app/pipes/array/sample';
import { ShufflePipe } from 'ngx-pipes/src/app/pipes/array/shuffle';
import { Observable } from 'rxjs';
import 'rxjs/add/observable/from';
import 'rxjs/add/observable/forkJoin';
enum QuizState {
idle,
running,
finished
}
@Component({
selector: 'page-quiz',
templateUrl: 'quiz.html',
providers: [
SamplePipe, ShufflePipe, QuizLoaderService
],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class QuizPage {
private slides: Slides;
private status: QuizState = QuizState.idle;
private questions: Array<QuizType|QuizDefinition> = [];
private readonly numberOfQuestions = 10;
// make enum accessable from the view
readonly QuizState = QuizState;
constructor(public navCtrl: NavController, private quizLoaderService: QuizLoaderService) {}
@ViewChild(Slides) set slidesViewChild(slides: Slides) {
if(slides) {
slides.onlyExternal = true;
slides.ionSlideWillChange.subscribe(slides => {
// load the after next question in advance
if(!slides.isEnd()) {
let index: number = slides.getActiveIndex() + 1;
let quizType: QuizType = <QuizType>this.questions[index];
this.quizLoaderService.loadQuizItem(quizType).subscribe((item: QuizDefinition) => this.questions[index] = item);
}
});
}
this.slides = slides;
}
startQuiz() {
this.status = QuizState.running;
// generate an array of question types
this.questions = this.quizLoaderService.getQuizItems(this.numberOfQuestions);
// fetch data for the first two questions
let startingQuestions: Observable<QuizDefinition>[] = [0, 1].map(index => {
let quizType = <QuizType>this.questions[index];
return this.quizLoaderService.loadQuizItem(quizType);
});
Observable.forkJoin(startingQuestions).subscribe(
// update first two items with actual question data
(items: QuizDefinition[]) => this.questions.splice(0, items.length, ...items)
);
}
...
}
从'@angular/core'导入{Component,ViewChild,ChangeDetectionStrategy};
从“离子角度”导入{NavController,Slides};
从“../../components/Quit item/Quit loader.service”导入{QuizLoaderService,QuizType,QuizDefinition};
从“ngx pipes/src/app/pipes/array/sample”导入{SamplePipe};
从“ngx pipes/src/app/pipes/array/shuffle”导入{shufflepe};
从“rxjs”导入{Observable};
导入“rxjs/add/observable/from”;
导入“rxjs/add/observable/forkJoin”;
枚举QuizState{
闲置的
跑步
完成
}
@组成部分({
选择器:“页面测验”,
templateUrl:'quick.html',
供应商:[
采样管、ShufflePipe、QuizLoaderService
],
changeDetection:ChangeDetectionStrategy.OnPush
})
导出类QuizPage{
私人幻灯片:幻灯片;
私有状态:QuizState=QuizState.idle;
私人问题:数组=[];
私人只读numberOfQuestions=10;
//使枚举可从视图访问
只读QuizState=QuizState;
构造函数(公共navCtrl:NavController,私有quizLoaderService:quizLoaderService){}
@ViewChild(幻灯片)设置幻灯片ViewChild(幻灯片:幻灯片){
如果(幻灯片){
slides.onlyExternal=true;
slides.ionSlideWillChange.subscribe(幻灯片=>{
//提前加载下一个问题之后的内容
如果(!slides.isEnd()){
let index:number=slides.getActiveIndex()+1;
让quizType:quizType=this.questions[index];
this.quizLoaderService.loadQuizItem(quizType).subscribe((item:QuizDefinition)=>this.questions[index]=item);
}
});
}
this.slides=幻灯片;
}
startQuiz(){
this.status=QuizState.running;
//生成问题类型数组
this.questions=this.quizLoaderService.getQuizItems(this.numberOfQuestions);
//获取前两个问题的数据
让我们开始提问:可观察[]=[0,1]。地图(索引=>{
让quizType=this.questions[index];
返回这个.quizLoaderService.loadQuizItem(quizType);
});
可观察。forkJoin(开始问题)。订阅(
//使用实际问题数据更新前两项
(items:QuizDefinition[])=>this.questions.splice(0,items.length,…items)
);
}
...
}
首先,questions
数组只填充QuizTypes
,这样就可以创建幻灯片了。然后从数据库中加载前两个问题的问题数据(QuizDefinition
)。当进入下一个问题时,我加载问题的数据
在我的电脑上,这与预期的一样有效,但在手机上,当呈现视图或无法识别更改时,第一个问题不会更新。无论如何,JSONPipe
仍然显示问题类型QuizType
,而不是问题数据。第一张幻灯片之后的任何幻灯片都能正常工作
编辑
在我的电脑上,我使用了一个数据库模型。没有耽搁。我添加了一个随机延迟,现在它的行为与移动设备上的相同。第一个问题数据没有设置。我现在解决了这个问题,切换到完全手动控制更改检测,并且只在预期确实会发生更改时运行它
import { Component, ViewChild, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core';
import { NavController, Slides } from 'ionic-angular';
import { QuizLoaderService, QuizType, QuizDefinition } from '../../components/quiz-item/quiz-loader.service';
import { SamplePipe } from 'ngx-pipes/src/app/pipes/array/sample';
import { ShufflePipe } from 'ngx-pipes/src/app/pipes/array/shuffle';
import { Observable } from 'rxjs';
import 'rxjs/add/observable/forkJoin';
enum QuizState {
idle,
running,
finished
}
@Component({
selector: 'page-quiz',
templateUrl: 'quiz.html',
providers: [
SamplePipe, ShufflePipe, QuizLoaderService
],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class QuizPage {
private slides: Slides;
private status: QuizState = QuizState.idle;
private questions: Array<QuizType|QuizDefinition> = [];
private readonly numberOfQuestions = 10;
// make enum accessable from the view
readonly QuizState = QuizState;
constructor(public navCtrl: NavController, private quizLoaderService: QuizLoaderService, private changeDetectorRef: ChangeDetectorRef) {}
ngAfterViewInit() {
// disable change detection
this.changeDetectorRef.detach();
}
...
startQuiz() {
this.status = QuizState.running;
this.questions = this.quizLoaderService.getQuizItems(this.numberOfQuestions);
//this.changeDetectorRef.detectChanges();
// fetch data for the first two questions
let startingQuestions: Observable<QuizDefinition>[] = [0, 1].map(index => {
let quizType = <QuizType>this.questions[index];
return this.quizLoaderService.loadQuizItem(quizType);
});
Observable.forkJoin(startingQuestions).subscribe((items: QuizDefinition[]) => {
this.questions.splice(0, items.length, ...items);
// run change detection when changes happen
this.changeDetectorRef.detectChanges();
});
}
...
}
从'@angular/core'导入{Component,ViewChild,ChangeDetectionStrategy,ChangeDetectorRef};
从“离子角度”导入{NavController,Slides};
从“../../components/Quit item/Quit loader.service”导入{QuizLoaderService,QuizType,QuizDefinition};
从“ngx pipes/src/app/pipes/array/sample”导入{SamplePipe};
从“ngx pipes/src/app/pipes/array/shuffle”导入{shufflepe};
从“rxjs”导入{Observable};
导入“rxjs/add/observable/forkJoin”;
枚举QuizState{
闲置的
跑步
完成
}
@组成部分({
选择器:“页面测验”,
templateUrl:'quick.html',
供应商:[
采样管、ShufflePipe、QuizLoaderService
],
changeDetection:ChangeDetectionStrategy.OnPush
})
导出类QuizPage{
私人幻灯片:幻灯片;
私有状态:QuizState=QuizState.idle;
私人问题:数组=[];
私人只读numberOfQuestions=10;
//使枚举可从视图访问
只读QuizState=QuizState;
构造函数(公共navCtrl:NavController,私有quizLoaderService:quizLoaderService,私有changeDetectorRef:changeDetectorRef){}
ngAfterViewInit(){
//禁用更改检测
this.changeDetectorRef.detach();
}
...
startQuiz(){
this.status=QuizState.running;
this.questions=this.quizLoaderService.getQuizItems(this.numberOfQuestions);
//this.changeDetectorRef.detectChanges();
//获取前两个问题的数据
让我们开始提问:可观察[]=[0,1]。地图(索引=>{
让quizType=this.questions[index];
返回这个.quizLoaderService.loadQuizItem(quizType);
});
Observable.forkJoin(startingQuestions).subscribe((项目:QuizDefinition[])=>{
这个.问题.拼接(0,items.length,…items);
//发生更改时运行更改检测
this.changeDetectorRef.detectChanges();
});
}
...
}