我正在使用以前的大型角度2应用程序的经验。我一直非常小心地控制渲染周期。保存日志是我如何调查发生的事情。
控制器
public debugTemplate() {
DEBUG.render && debug('Render FooCmp');
}
模板
{{ debugTemplate() }}
我一直在智能组件中只使用ngrx状态商店订阅。这样我就可以完全避免使用ActivatedRouteSnapshot
或RouteReuseStrategy
保护
import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot,
RouterStateSnapshot } from '@angular/router';
import { Observable } from 'rxjs/Observable';
import { environment } from '../../../environments/environment';
import { DEBUG } from '../../../config/config';
import * as Debug from 'debug';
// Interfaces
import { Foo } from '../interfaces/foo';
// Services
import { BarService } from '../services/bar.service';
import { FooService } from '../services/foo.service';
// Debug
const debugOff = (...any) => { }, debug = Debug('app:FooPageGuard');
@Injectable()
export class FooPageGuard implements CanActivate {
constructor(
private _barService: BarService,
private _fooService: FooService
) {
DEBUG.constr && debug('Construct FooPageGuard');
}
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<boolean> {
DEBUG.guard && debug('Guard FooPageGuard');
return this._fooService.foo$().switchMap(
foo => this._barService.getBar(foo)
)
.map(data => { if (data) {return true} })
.first() // Take first and enable the route
.do(foo => DEBUG.guard && debug('Guard OK FooPageGuard:', foo))
}
}
带有ChangeDetectionStrategy.OnPush
的智能组件
// Ngrx state store subscription
this._fooService.foo$().subscribe(exp => this.foo = exp);
使用ng serve --prod --aot
我已经能够看到,如果我使用防护而不是解析器,则会在onlz上执行父组件的渲染。使用解析器会导致多个渲染以获得相同的初始状态。在Angular文档中,建议使用防火墙进行数据检索的登录和解析器。如果你有很多数据流被解析为异步,这看起来会以多个浪费的渲染为代价。
所以问题。可以绕过这个惯例吗?在组件中使用ngrx状态存储订阅和放弃解析器+路由订阅,以支持触发数据请求的警卫。
另一个奇怪的行为是,无论我最初做什么,我仍然有一些AppCmp
渲染,这些渲染似乎是由观察者自己在儿童补偿甚至Init
编辑之前触发的。
修改
我今天遇到了一些麻烦。将OnPush
用于容器组件(如页面(智能组件))是错误的。订阅将触发,但模板将不会收到更新的值。由于没有触发输入,因此可以从OnPush获得。所以我只在愚蠢的组件上使用OnPush,这仍然是一个重大改进,因为他们做了大量的努力工作。
编辑2 - 使用解析器,而不是警卫
嗯......这没有达到预期效果。我们只想说,如果你有一个尚未发射的可观测量,那么守卫将永久地阻止流动。所以我的花哨的例子只是因为observable已经有一些映射到true的值。在彻底清理后,我发现我的应用程序停止了工作。
实质上,以下基本示例适用于解析程序,但不适用于防护。这是因为观察者在要求它的那一刻不能得到任何价值,所以他只是认为这是不行的。我只需要进一步调查这些额外渲染的来源。某处必须有一些错误的代码。
return Observable.interval(1000)
.take(1) // Needed to trigger the guard. Resolvers do just fine without
.map(() => true )
答案 0 :(得分:0)
使用解析器,而不是警卫
嗯......这没有达到预期效果。我们只想说,如果你有一个尚未发射的可观测量,那么守卫将永久地阻止流动。所以我的花哨的例子只是因为observable已经有一些映射到true的值。在彻底清理后,我发现我的应用程序停止了工作。
实质上,以下基本示例适用于解析程序,但不适用于防护。这是因为观察者在要求它的那一刻不能得到任何价值,所以他只是认为这是不行的。我只需要进一步调查这些额外渲染的来源。某处必须有一些错误的代码。
return Observable.interval(1000)
.take(1) // Needed to trigger the guard. Resolvers do just fine without
.map(() => true )