我正在构建以前的大型 Angular 2 应用程序的经验。我一直非常小心地控制渲染周期。记录日志是我调查发生的事情的方式。
Controller
public debugTemplate() {
DEBUG.render && debug('Render FooCmp');
}
模板
{{ debugTemplate() }}
我一直在智能组件中只使用 ngrx state store 订阅。这样我就可以完全避免使用 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
如果我使用守卫而不是解析器,我已经能够看到父组件的渲染只执行一次。使用解析器会导致多次渲染以获得相同的初始状态。在 Angular 文档中,建议使用保护器进行登录,使用解析器进行数据检索。如果您有大量数据流被异步解析,那么看起来这是以多次浪费渲染为代价的。
所以问题。可以绕过这个约定吗?在组件中使用 ngrx 状态存储订阅并放弃解析器 + 路由订阅,以支持触发数据请求的守卫。
另一个奇怪的行为是,无论我最初做什么,我仍然有一些 AppCmp
渲染,它们似乎在子组件 Init
之前由 observables 本身触发>编辑。
编辑
我今天遇到了一些麻烦。将 OnPush
用于页面(智能组件)等容器组件是错误的。订阅将触发,但模板不会收到更新的值。这是 OnPush 所期望的,因为没有触发任何输入。所以我只在dumb组件上使用 OnPush,这仍然是一个显着的改进,因为它们完成了大部分艰苦的工作。
编辑 2 - 使用解析器,而不是守卫
好吧...这没有按预期进行。我们只是说,如果您有一个尚未触发的可观察对象,守卫将简单地永久阻止流。所以我的奇特示例之所以有效,是因为可观察对象内部已经有一些值映射到 true。彻底清理后,我发现我的应用停止工作了。
本质上,以下基本示例在解析器中工作,但在守卫中不起作用。这是因为 Observable 在他要求的那一刻无法获得任何值(value),所以他只是假设这是不行的。我只需要进一步调查那些额外的效果图是从哪里来的。某处一定有一些错误的代码。
return Observable.interval(1000)
.take(1) // Needed to trigger the guard. Resolvers do just fine without
.map(() => true )
最佳答案
使用解析器,而不是守卫
好吧...这没有按预期进行。我们只是说,如果您有一个尚未触发的可观察对象,守卫将简单地永久阻止流。所以我的奇特示例之所以有效,是因为可观察对象内部已经有一些值映射到 true。彻底清理后,我发现我的应用停止工作了。
本质上,以下基本示例在解析器中工作,但在守卫中不起作用。这是因为 Observable 在他要求的那一刻无法获得任何值(value),所以他只是假设这是不行的。我只需要进一步调查那些额外的效果图是从哪里来的。某处一定有一些错误的代码。
return Observable.interval(1000)
.take(1) // Needed to trigger the guard. Resolvers do just fine without
.map(() => true )
关于javascript - 我应该使用守卫而不是解析器来保存 Angular 2 中的渲染周期吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46642006/