Angular6 Form 仅在定期 zone.js 变化检测后响应
Angular6 Form only responds after periodic zone.js change detection
我有一个很奇怪的情况:在设置一个包含表单的组件后,与表单的交互非常慢。
单击下拉列表后,表单仅在 zone.js 超时发生并且周期性更改检测开始时才会做出反应。
知道为什么会这样吗?为什么 component/form 会在 zone.js 变化检测之外?我没有任何错误。
我唯一的调试输入是,在 chrome devtools 中进行性能分析时,我得到了点击事件,然后在 5-12 秒后,zone.js 触发了 UI 动画显示下拉选项。
在 Chrome DevTools Performance Profiler 中,如下所示:
我在分析后大约 2 秒点击下拉菜单:
然后 10 秒后,zone.js 执行触发下拉列表的定期更新:
两者之间,什么也没有发生。
我正在使用 NgRx,切换到具有表单的组件发生在 @Effect 中,我在其中调用路由器。
效果是这样的:
(它也不适用于 RxJS5,所以它不应该与迁移有任何关系)
@Effect()
placesDetails$ = this.actions$
.ofType<PlaceSelectedAction>(PLACE_SELECTED_ACTION)
.pipe(
switchMap((action: PlaceSelectedAction) =>
this.placesService.loadPlacesDetails(action.payload)
),
map(data => new PlaceDetailsLoadedAction(data)),
tap(_ => this.router.navigate(["/place-details"]))
);
组件本身是这样的:
import { Component } from "@angular/core";
import { Store } from "@ngrx/store";
import { ApplicationState } from "../store/application-state";
import { Router } from "@angular/router";
import { Card } from "../../../../shared/model/card";
@Component({
selector: "app-place-details",
templateUrl: "./place-details.component.html",
styleUrls: ["./place-details.component.scss"]
})
export class PlaceDetailsComponent {
card: Card;
constructor(private store: Store<ApplicationState>, private router: Router) {
this.store.subscribe(state => (this.card = state.cardDataState.card));
}
travelTypeLocation = [
{ value: "city", viewValue: "City" },
{ value: "beach", viewValue: "Beach" },
{ value: "mountains", viewValue: "Mountains" },
{ value: "countryside", viewValue: "Countryside" }
];
travelTypeActivity = [
{ value: "relax", viewValue: "Relax" },
{ value: "sports", viewValue: "Sports" },
{ value: "culture", viewValue: "Culture" },
{ value: "party", viewValue: "Party" }
];
travelTypeCompanions = [
{ value: "family", viewValue: "Family" },
{ value: "partner", viewValue: "Partner" },
{ value: "single", viewValue: "Single" },
{ value: "friends", viewValue: "Friends" },
{ value: "colleagues", viewValue: "Colleagues" }
];
checkPlaceDetails() {
//this.store.dispatch(new PlaceDetailsSubmitAction());
}
goBack() {
this.router.navigate(["/search-places"]);
}
}
这是HTML:
<div class="container" fxLayout.xs="column">
<h3>Fill out Place Details</h3>
<form>
<mat-form-field class="full-width">
<input
matInput
placeholder="Title"
type="text"
required
name="title"
[(ngModel)]="card.title">
<mat-error *ngIf="card.title">{{ card.title }}</mat-error>
</mat-form-field>
<mat-form-field class="full-width">
<input
matInput
placeholder="Description"
type="text"
name="description"
required
[(ngModel)]="card.description"
/>
</mat-form-field>
<mat-form-field class="full-width">
<mat-select
placeholder="Travel Type Location"
name="travelTypeLocation"
required
[(ngModel)]="card.travelTypeLocation"
>
<mat-option *ngFor="let type of travelTypeLocation" [value]="type.value">
{{ type.viewValue }}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field class="full-width">
<input
matInput
placeholder="Travel Dimension Location (e.g. surfing, biking, museum, theater)"
type="text"
name="travelDimensionLocation"
required
[(ngModel)]="card.travelDimensionLocation"
/>
</mat-form-field>
<mat-form-field class="full-width">
<mat-select
placeholder="Travel Type Activity"
name="travelTypeActivity"
required
[(ngModel)]="card.travelTypeActivity"
>
<mat-option *ngFor="let type of travelTypeActivity" [value]="type.value">
{{ type.viewValue }}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field class="full-width">
<input
matInput
placeholder="Travel Dimension Activity (e.g. modern city, historic city, hills, high mountains)"
type="text"
name="travelDimensionActivity"
required
[(ngModel)]="card.travelDimensionActivity"
/>
</mat-form-field>
<mat-form-field class="full-width">
<mat-select
placeholder="Travel Companions"
name="travelTypeCompanions"
required
[(ngModel)]="card.travelTypeCompanions"
>
<mat-option *ngFor="let type of travelTypeCompanions" [value]="type.value">
{{ type.viewValue }}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field class="full-width">
<input
matInput
placeholder="Duration"
type="text"
required
name="duration"
[(ngModel)]="card.averageDuration"
/>
</mat-form-field>
<mat-form-field class="full-width">
<input
matInput
required
placeholder="Cost (€)"
type="number"
name="cost"
[(ngModel)]="card.cost"
/>
</mat-form-field>
<button mat-raised-button color="primary" (click)="checkPlaceDetails()">Add Card</button>
<button mat-raised-button color="secondary" (click)="goBack()">Go Back</button>
</form>
</div>
请告诉我什么是重要的?我迷路了。
谢谢!
这个很难弄清楚。但显然 zone.js 和 RxJS 存在错误。
在 polyfills
中包含 import 'zone.js/dist/zone-patch-rxjs';
后,它现在按预期工作,在表单交互后没有延迟。
我有一个很奇怪的情况:在设置一个包含表单的组件后,与表单的交互非常慢。 单击下拉列表后,表单仅在 zone.js 超时发生并且周期性更改检测开始时才会做出反应。 知道为什么会这样吗?为什么 component/form 会在 zone.js 变化检测之外?我没有任何错误。
我唯一的调试输入是,在 chrome devtools 中进行性能分析时,我得到了点击事件,然后在 5-12 秒后,zone.js 触发了 UI 动画显示下拉选项。
在 Chrome DevTools Performance Profiler 中,如下所示:
我在分析后大约 2 秒点击下拉菜单:
然后 10 秒后,zone.js 执行触发下拉列表的定期更新:
两者之间,什么也没有发生。
我正在使用 NgRx,切换到具有表单的组件发生在 @Effect 中,我在其中调用路由器。
效果是这样的: (它也不适用于 RxJS5,所以它不应该与迁移有任何关系)
@Effect()
placesDetails$ = this.actions$
.ofType<PlaceSelectedAction>(PLACE_SELECTED_ACTION)
.pipe(
switchMap((action: PlaceSelectedAction) =>
this.placesService.loadPlacesDetails(action.payload)
),
map(data => new PlaceDetailsLoadedAction(data)),
tap(_ => this.router.navigate(["/place-details"]))
);
组件本身是这样的:
import { Component } from "@angular/core";
import { Store } from "@ngrx/store";
import { ApplicationState } from "../store/application-state";
import { Router } from "@angular/router";
import { Card } from "../../../../shared/model/card";
@Component({
selector: "app-place-details",
templateUrl: "./place-details.component.html",
styleUrls: ["./place-details.component.scss"]
})
export class PlaceDetailsComponent {
card: Card;
constructor(private store: Store<ApplicationState>, private router: Router) {
this.store.subscribe(state => (this.card = state.cardDataState.card));
}
travelTypeLocation = [
{ value: "city", viewValue: "City" },
{ value: "beach", viewValue: "Beach" },
{ value: "mountains", viewValue: "Mountains" },
{ value: "countryside", viewValue: "Countryside" }
];
travelTypeActivity = [
{ value: "relax", viewValue: "Relax" },
{ value: "sports", viewValue: "Sports" },
{ value: "culture", viewValue: "Culture" },
{ value: "party", viewValue: "Party" }
];
travelTypeCompanions = [
{ value: "family", viewValue: "Family" },
{ value: "partner", viewValue: "Partner" },
{ value: "single", viewValue: "Single" },
{ value: "friends", viewValue: "Friends" },
{ value: "colleagues", viewValue: "Colleagues" }
];
checkPlaceDetails() {
//this.store.dispatch(new PlaceDetailsSubmitAction());
}
goBack() {
this.router.navigate(["/search-places"]);
}
}
这是HTML:
<div class="container" fxLayout.xs="column">
<h3>Fill out Place Details</h3>
<form>
<mat-form-field class="full-width">
<input
matInput
placeholder="Title"
type="text"
required
name="title"
[(ngModel)]="card.title">
<mat-error *ngIf="card.title">{{ card.title }}</mat-error>
</mat-form-field>
<mat-form-field class="full-width">
<input
matInput
placeholder="Description"
type="text"
name="description"
required
[(ngModel)]="card.description"
/>
</mat-form-field>
<mat-form-field class="full-width">
<mat-select
placeholder="Travel Type Location"
name="travelTypeLocation"
required
[(ngModel)]="card.travelTypeLocation"
>
<mat-option *ngFor="let type of travelTypeLocation" [value]="type.value">
{{ type.viewValue }}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field class="full-width">
<input
matInput
placeholder="Travel Dimension Location (e.g. surfing, biking, museum, theater)"
type="text"
name="travelDimensionLocation"
required
[(ngModel)]="card.travelDimensionLocation"
/>
</mat-form-field>
<mat-form-field class="full-width">
<mat-select
placeholder="Travel Type Activity"
name="travelTypeActivity"
required
[(ngModel)]="card.travelTypeActivity"
>
<mat-option *ngFor="let type of travelTypeActivity" [value]="type.value">
{{ type.viewValue }}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field class="full-width">
<input
matInput
placeholder="Travel Dimension Activity (e.g. modern city, historic city, hills, high mountains)"
type="text"
name="travelDimensionActivity"
required
[(ngModel)]="card.travelDimensionActivity"
/>
</mat-form-field>
<mat-form-field class="full-width">
<mat-select
placeholder="Travel Companions"
name="travelTypeCompanions"
required
[(ngModel)]="card.travelTypeCompanions"
>
<mat-option *ngFor="let type of travelTypeCompanions" [value]="type.value">
{{ type.viewValue }}
</mat-option>
</mat-select>
</mat-form-field>
<mat-form-field class="full-width">
<input
matInput
placeholder="Duration"
type="text"
required
name="duration"
[(ngModel)]="card.averageDuration"
/>
</mat-form-field>
<mat-form-field class="full-width">
<input
matInput
required
placeholder="Cost (€)"
type="number"
name="cost"
[(ngModel)]="card.cost"
/>
</mat-form-field>
<button mat-raised-button color="primary" (click)="checkPlaceDetails()">Add Card</button>
<button mat-raised-button color="secondary" (click)="goBack()">Go Back</button>
</form>
</div>
请告诉我什么是重要的?我迷路了。
谢谢!
这个很难弄清楚。但显然 zone.js 和 RxJS 存在错误。
在 polyfills
中包含 import 'zone.js/dist/zone-patch-rxjs';
后,它现在按预期工作,在表单交互后没有延迟。