【问题标题】:Angular2 - Extending router and ObservableAngular2 - 扩展路由器和 Observable
【发布时间】:2016-10-19 17:19:28
【问题描述】:

在带有路由器模块 v 3.0.0.6alpha 的 angular2 rc2 中,我扩展了 RouterOulet 以在访问管理员之前检查用户是否已登录。所以这是代码:

@Directive({
    selector: 'router-outlet'
})

export class LoggedInRouterOutlet extends RouterOutlet 
{
    publicRoutes: Array<string>;
    private parentOutletMap: RouterOutletMap;
    private userService: UserService;
    private parentRouter: Router;

    constructor(
        parentOutletMap: RouterOutletMap,
        _location: ViewContainerRef,
        @Attribute('name') name: string,
        userService: UserService,
        parentRouter: Router
    ) { 
        super(parentOutletMap, _location, name);

        this.parentRouter = parentRouter;
        this.parentOutletMap = parentOutletMap;
        this.userService = userService;
        this.publicRoutes = [
            'public', 
            'login'
        ];
    }

    activate(factory: ComponentFactory<any>, activatedRoute: ActivatedRoute, providers: ResolvedReflectiveProvider[], outletMap: RouterOutletMap) 
    {
        if (this._canActivate(factory.selector)) { 
            return super.activate(factory, activatedRoute, providers, outletMap); 
        }

        this.parentRouter.navigate(['/login']);
    }

    _canActivate(url) {
        return this.publicRoutes.indexOf(url) !== -1 || this.userService.isLoggedIn()
    }
}

userService.isLoggedIn() 必须返回一个布尔值。我的问题是:如何调整我的代码以进行 http 调用以检查用户是否已登录?因为如果 isLoggedIn 方法返回一个 observable 对象,而我订阅了它,我无法在父函数中返回结果。

【问题讨论】:

    标签: javascript node.js login angular angular2-router


    【解决方案1】:

    请注意 OutletRouter 的 activate 方法的结果已经改变。

    @angular/router-deprecated

    activate(nextInstruction: ComponentInstruction) : Promise&lt;any&gt;

    @angular/路由器

    activate(factory: ComponentFactory&lt;any&gt;, providers: ResolvedReflectiveProvider[], outletMap: RouterOutletMap) : ComponentRef&lt;any&gt;

    这不再是 Promise 或 Observable 了。新的路由器实现附带了一个我认为更简洁的解决方案:Guards。

    守卫的返回值控制路由器的行为:

    如果返回true,则导航过程如果返回则继续 false,导航过程停止,用户原地不动 还可以告诉路由器导航到其他地方,有效地取消 当前导航。

    守卫可能会同步返回其布尔值答案。但在许多 在这种情况下,守卫不能同步产生答案。守卫 可以向用户提问,将更改保存到服务器,或获取 新鲜的数据。这些都是异步操作。

    因此,路由守卫可以返回一个 Observable 和 路由器将等待 observable 解析为 true 或 `false。

    你可以创建 auth.guard.ts:

    import { Injectable }             from '@angular/core';
    import { CanActivate,
             Router,
             ActivatedRouteSnapshot,
             RouterStateSnapshot }    from '@angular/router';
    import { UserService }            from './user.service';
    
    @Injectable()
    export class AuthGuard implements CanActivate {
      constructor(private userService: UserService, private router: Router) {}
    
      canActivate(
        // Not using but worth knowing about
        next:  ActivatedRouteSnapshot,
        state: RouterStateSnapshot
      ) {
        return this.userService.isLoggedIn();
      }
    }
    

    现在确保您的 isLoggedIn 返回 Observable(或 Promise - 尝试两者,因为 Angular2 参考是 not ready yet)。在我的例子中,API 返回 JSON 格式:{ success: true / false }。

    public isLoggedIn() : Observable<boolean> | boolean {
        let router: Router = this.router;
        let obs;
    
        try {
            obs = this.authHttp.get('/api/check/logged')
                .map(result => result.json())
                .map(resultJson => (resultJson && resultJson.success));
    
        } catch (err) {
            obs = Observable.of(false);
        }
    
        return obs
            .map(success => {
                 // navigate to login page
                 if (!success)
                     router.navigate(['/auth/login']);
    
                 return success;
            });
    }
    

    然后只需修改您的 RouterConfig 数组:

    { path: '/secret', component: SercetComponent, canActivate: [AuthGuard] }
    

    另请参阅Angular2 Developer Guide

    【讨论】:

    • 看起来不错,谢谢!但我想知道在哪里注入那个守卫?如果您可以编辑代码以显示它...
    • 我在发布原始答案几分钟后做了;)我之前忘记添加了。
    • 整洁!再次感谢
    • 我实现了代码并得到“没有 AuthGuard 提供者”,但我将它添加到我的主要组件提供者中。你知道为什么吗?
    • 不。您可能没有正确的路由器包(它不在 2.0.0-rc.2 中)。添加到 package.json 中的依赖项:“@angular/router”:“^3.0.0-alpha.3”并更新。你应该得到它:)
    猜你喜欢
    • 1970-01-01
    • 2017-01-30
    • 1970-01-01
    • 2018-11-06
    • 1970-01-01
    • 1970-01-01
    • 2016-11-14
    • 2016-07-25
    • 1970-01-01
    相关资源
    最近更新 更多