3

在带有路由器模块 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 对象,并且我订阅了它,我无法在父函数中返回结果。

4

1 回答 1

8

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

@angular/路由器已弃用

activate(nextInstruction: ComponentInstruction) : Promise<any>

@角/路由器

activate(factory: ComponentFactory<any>, providers: ResolvedReflectiveProvider[], outletMap: RouterOutletMap) : ComponentRef<any>

这不再是 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 参考尚未准备好)。在我的例子中,API 返回 JSON 格式:{成功:真/假}。

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 开发人员指南

于 2016-06-17T19:43:57.183 回答