javascript - 我应该使用守卫而不是解析器来保存 Angular 2 中的渲染周期吗?

标签 javascript angular ngrx

我正在构建以前的大型 Angular 2 应用程序的经验。我一直非常小心地控制渲染周期。记录日志是我调查发生的事情的方式。

Controller

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

模板

{{ debugTemplate() }}

我一直在智能组件中只使用 ngrx state store 订阅。这样我就可以完全避免使用 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 如果我使用守卫而不是解析器,我已经能够看到父组件的渲染只执行一次。使用解析器会导致多次渲染以获得相同的初始状态。在 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/

相关文章:

javascript - 在现有网站中实现 Nodejs 应用程序

javascript - 将 for 循环变成 lodash _.forEach

Angular 2 和 Ionic 2 : What are the differences between constructor, ionViewDidLoad 和 ngOnInit 方法

Angular ngrx@effect 基本问题 : Type 'Observable<void>' is not assignable to type

angular - 将 NgRx 和 Angular 升级到版本 7 后无法编译

javascript - yarn ,例如 :'live-server' 未被识别为内部或外部命令

javascript - Three.js 合并网格但保留单独的 Material

javascript - 在 TypeScript 中访问从另一个类实例化的对象

javascript - Jhipster Angular 4 额外的 CSS 和 JS

redux - 在效果失败/错误的情况下防止路由器导航