【问题标题】:How to run function when angular component is rendered?渲染角度组件时如何运行功能?
【发布时间】:2018-03-16 10:18:25
【问题描述】:

MyComponent 使用服务来获取数据,然后呈现该数据。但是,服务无法获取数据,直到用户登录。如果用户第一次访问路由'/myPage',容器组件将显示登录组件。但是,即使呈现登录组件而不是 ng-content(其计算结果为 MyComponent),MyComponent 也会由 angular 初始化并获取并导致服务在登录之前过早获取数据。因此,当用户成功登录和 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);

    }
  }

【问题讨论】:

  • 您正在寻找:angular.io/api/core/AfterViewInit。使用方式与 OnInit 相同(导入,实现,然后使用 ngAfterViewInit () { ... })
  • 我认为你走错路了。因为在您的情况下,您需要在任何地方添加您的条件以检查用户是否已登录。这意味着组件已加载,我们可以找到所有 js 文件并进行检查。也许有人可以进行一些 xss 攻击。在 Angular 中,我们有更好的方法来构建守卫。在那里你可以找到一个很好的例子:jasonwatmore.com/post/2016/09/29/…
  • @RomaSkydan 感谢您提供的信息。但我不确定安全问题是什么?是的,客户端检查登录用户,但我也有一个带有令牌的安全检查服务器端(这就是我需要在用户登录后获取数据的原因)。您能否详细说明安全问题出在哪里?
  • @Z.Bagley 不幸的是,当我替换 ngOnInit 时,该生命周期方法不起作用

标签: angular


【解决方案1】:

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

路线守卫

例如,显示登录对话框的一种常见方法是使用路由保护而不是 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

【讨论】:

    【解决方案2】:

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

    问题在于 Angular 如何处理 ngIf。 ngIf 中的组件总是“初始化”,无论它们是否显示。要防止这种行为,请改用模板。

    Angular4 ng-content gets built when ngIf is false

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-03-05
      • 2021-04-21
      • 2020-03-26
      • 1970-01-01
      • 1970-01-01
      • 2020-01-31
      • 2020-11-18
      • 2019-06-16
      相关资源
      最近更新 更多