如何在渲染角度组件时运行函数?

时间:2017-10-04 21:48:41

标签: angular

MyComponent使用服务获取数据,然后呈现该数据。但是,在用户登录之前,服务无法获取数据。如果用户前往路线' / myPage'容器组件第一次将显示登录组件。但是,即使渲染登录组件而不是ng-content(其评估为MyComponent),MyComponent也会被angular和fetches初始化,并导致服务在登录之前过早地获取数据。因此,当用户成功登录时,MyComponent最后呈现,初始数据服务没有返回任何数据。

如何在呈现组件之前推迟数据提取?我在MyComponent中尝试了所有不同的生命周期方法但没有成功。

app.component

<container>
    <router-outlet></router-outlet>
</container>

容器组件

<div *ngIf="!userService.getLoggedInUser()">
  <login></login>
</div>

<div *ngIf="userService.getLoggedInUser()">
  <ng-content></ng-content>
</div>

路由模块

const routes: Routes = [
  { path: 'myPage', component: myComponent }
];

我的组件

export class MyComponent {
  data

  constructor(private dataService: DataService) {}

    ngOnInit () {
      //how can i make run this service AFTER the component renders? i know
      //ngOnInit is definitely not the correct lifecycle method, but what is?
      this.dataService.get().then((data) => this.data = data);

    }
  }

2 个答案:

答案 0 :(得分:2)

ngOnInit是用于检索组件数据的常规方法。所以,如果某些东西不起作用,我的猜测是其他地方存在问题。

Route Guard

例如,呈现登录对话框的一种常用方法是使用路由保护而不是ngIf。这看起来像这样:

import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, RouterStateSnapshot, Router,
         CanActivate } from '@angular/router';

import { AuthService } from './auth.service';

@Injectable()
export  class AuthGuard implements CanActivate {

    constructor(private authService: AuthService,
                private router: Router) { }

    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
        return this.checkLoggedIn(state.url);
    }

    checkLoggedIn(url: string): boolean {
        if (this.authService.isLoggedIn()) {
            return true;
        }

        // Retain the attempted URL for redirection
        this.authService.redirectUrl = url;
        this.router.navigate(['/login']);
        return false;
    }
}

然后在需要登录的任何路线上使用此警戒:

                { path: 'welcome', component: WelcomeComponent },
                {
                    path: 'movies',
                    canActivate: [AuthGuard],
                    loadChildren: './movies/movie.module#MovieModule'
                },
                { path: '', redirectTo: 'welcome', pathMatch: 'full' },

这样可以防止过早地路由到组件。

路线解析器

您可以考虑的另一个选择是使用路线解析器。它允许您在路由到特定组件之前检索路由的数据。

我不确定这会对您的情况有所帮助,但可能值得一看。

我在这里有一个例子:https://github.com/DeborahK/MovieHunter-routing

答案 1 :(得分:0)

虽然这个问题肯定表明我的身份证明模式存在问题,但我想把这些发现留给任何偶然发现这个问题的人。

问题在于角度如何处理ngIf。 ngIf中的组件始终&#34;初始化&#34;无论是否显示。要防止此行为,请改用模板。

请参阅 Angular4 ng-content gets built when ngIf is false

话虽如此,即使使用模板,我的原始身份验证解决方案也不起作用,因为我无法将<router-outlet>嵌套到模板中。正确的解决方案是改变逻辑,并使用DeborahK建议的路线保护。