我应该使用防护而不是解析器来保存角度2中的渲染周期吗?

时间:2017-10-09 08:34:11

标签: javascript angular ngrx

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

控制器

public debugTemplate() {
    DEBUG.render && debug('Render FooCmp');
}

模板

{{ debugTemplate() }}

我一直在智能组件中只使用ngrx状态商店订阅。这样我就可以完全避免使用ActivatedRouteSnapshotRouteReuseStrategy

保护

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 )

1 个答案:

答案 0 :(得分:0)

使用解析器,而不是警卫

嗯......这没有达到预期效果。我们只想说,如果你有一个尚未发射的可观测量,那么守卫将永久地阻止流动。所以我的花哨的例子只是因为observable已经有一些映射到true的值。在彻底清理后,我发现我的应用程序停止了工作。

实质上,以下基本示例适用于解析程序,但不适用于防护。这是因为观察者在要求它的那一刻不能得到任何价值,所以他只是认为这是不行的。我只需要进一步调查这些额外渲染的来源。某处必须有一些错误的代码。

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