我应该使用防护装置而不是旋转变压器来保存角度2中的渲染周期吗?

Adr*_*isa 5 javascript ngrx angular

我正在利用以前的大型角度2应用程序的经验.我一直非常小心地控制渲染周期.保存日志是我如何调查发生的事情.

调节器

public debugTemplate() {
    DEBUG.render && debug('Render FooCmp');
}
Run Code Online (Sandbox Code Playgroud)

模板

{{ debugTemplate() }}
Run Code Online (Sandbox Code Playgroud)

我一直在智能组件中只使用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)) 

    }
}
Run Code Online (Sandbox Code Playgroud)

智能组件ChangeDetectionStrategy.OnPush

// Ngrx state store subscription
this._fooService.foo$().subscribe(exp => this.foo = exp);
Run Code Online (Sandbox Code Playgroud)

使用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 )
Run Code Online (Sandbox Code Playgroud)

Adr*_*isa 0

使用解析器,而不是警卫

嗯...这并没有按预期进行。假设您有一个尚未触发的可观察对象,则守卫将简单地永久阻止该流。所以我的奇特示例之所以有效,只是因为可观察量内部已经有一些映射到 true 的值。彻底清理后,我发现我的应用程序停止工作。

本质上,以下基本示例在解析器中运行,但在防护中不起作用。这是因为可观察者在他请求时无法获得任何价值,所以他只是认为这是不行的。我只需要进一步调查这些额外的渲染来自哪里。某处一定有一些错误的代码。

return  Observable.interval(1000)
    .take(1) // Needed to trigger the guard. Resolvers do just fine without
    .map(() => true )
Run Code Online (Sandbox Code Playgroud)