【问题标题】:Router navigate redirect after authentication does not render component身份验证后路由器导航重定向不呈现组件
【发布时间】:2016-07-07 04:17:23
【问题描述】:

我想在身份验证后重定向到我的主组件。重定向成功,但是 home 组件没有渲染。如果我将 this.router.navigate 移到 subscribe 块之外,它将正确呈现。

export class LoginComponent implements AfterViewInit {
    constructor(private router: Router,
                private authService: AuthenticationService) {

        this.authService.authenticationStream().subscribe(isAuthenticated => {
            if (isAuthenticated) {
                this.router.navigate(['/home']);
            }
        });
    }
}

在 chrome 开发工具中,我可以看到除 ngFor 块之外的所有主组件模板:

<md-grid-tile *ngFor="let tile of CONFIG.tiles">
    {{ tile }}
</md-grid-tile>

我可以验证 CONFIG.tiles 是否已填充。

为什么导航后不会渲染 ngFor 块,特别是来自 Observable 订阅内的导航调用?

编辑:添加 AuthenticationService 代码:

export class AuthenticationService {
    constructor(private http: HttpService,
              private store: Store<AppStore>) {
    }

    authenticate(): void {
        let uri = 'http://uri.com'
        this.http.post(uri).subscribe(() => {
            // Dispatch event to ngrx store if user is successfully authenticated
            this.store.dispatch({type: AUTHENTICATED});
        });
    }

    authenticationStream(): Observable<boolean> {
        // Emits events from dispatch calls
        return <Observable<boolean>> this.store.select(AUTHENTICATION);
    }
}

【问题讨论】:

  • 什么是authServiceauthenticationStream`?
  • authService.authenticationStream() 返回一个指示身份验证状态的布尔值的 Observable 流
  • 请添加显示它的代码

标签: angular angular2-routing


【解决方案1】:

听起来authenticationStream 会在 Angulars 区域之外发出事件,这会破坏更改检测并导致您描述的行为。

您可以使用zone.run() 强制执行回到 Angulars 区域:

export class LoginComponent implements AfterViewInit {
    constructor(private router: Router,
                private authService: AuthenticationService
                zone: NgZone) {

        this.authService.authenticationStream().subscribe(isAuthenticated => {
            if (isAuthenticated) {
                zone.run(() => this.router.navigate(['/home']));
            }
        });
    }
}

【讨论】:

  • 我认为可能值得调查为什么会发生这种情况,最好在代码开始在区域外运行的地方应用 zone.run() 但为此我需要查看更多代码 (@987654325 @ 以及使用它发出事件的位置)。
  • 嗨,Gunter,zone.run 是做什么的?创建一个新范围?
  • Angular2 在区域内运行代码。区域是一个范围,其中(大多数)异步 API(addEventHandlerremoveEventHandlersetTimeout,...)被修补,因此 Angular2 在发生某些事件时得到通知。每次发生事件并且所有事件处理程序都完成时,Angular2 都会运行更改检测。如果代码在 Angulars 区域之外运行,则不会发生更改检测,这会导致您描述的行为。 zone.run() 使执行线程(可能在 Angulars 区域之外)在其区域内继续。当使用一些未修补的异步 API 时,会发生在 Angulars 区域之外运行的代码。
  • 我不知道 store 或者是什么导致它在 Angulars 区域之外运行。即使看到更多代码,我也没有比上面的答案更好的解决方案。
  • 我遇到了类似的问题,并试图在 NgZone 中包装调用,但是看到你如何只在 zone.run 中包装订阅回调就可以了。一百万次感谢!
猜你喜欢
  • 2018-05-16
  • 1970-01-01
  • 2023-03-10
  • 2019-01-10
  • 1970-01-01
  • 1970-01-01
  • 2020-06-15
  • 1970-01-01
  • 2017-09-24
相关资源
最近更新 更多