【问题标题】:Angular2 router.navigate() not working first timeAngular2 router.navigate()第一次不工作
【发布时间】:2017-05-05 04:30:33
【问题描述】:

我定义了以下路线:

export const routes: Routes = [
    { path: '', component: HomeComponent, pathMatch: 'full', canActivate: [AuthGuardService] },
    { path: 'sites', component: SiteIndexComponent, resolve: { siteSummaries: SiteSummariesResolve }, canActivate: [AuthGuardService] },
    { path: 'qa-tasks', component: QaTaskIndexComponent, resolve: { investigations: InvestigationsResolve, reviews: ReviewsResolve }, canActivate: [AuthGuardService] },
    { path: 'error', component: ErrorComponent },
    { path: '**', redirectTo: '' }
];

我的应用程序的用户根据他们的角色看到完全不同的页面,包括他们的“登陆”(主页)页面。我正在使用我的 HomeComponent 根据以下角色将用户路由到正确的登录页面:

export class HomeComponent implements OnInit {

    private roles: any;

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

    ngOnInit() {
        var currentUser = this.authService.getCurrentUser();
        this.roles = currentUser.roles;
        this.redirect();
    }

    private redirect() {
        var route;
        if (this.inRole('site-user-role')) {
            route = 'sites';
        }
        else if (this.inRole('qa-user-role')) {
            route = 'qa-tasks';
        }
        if (route) {
            this.router.navigate([route]);
        }
        else {
            this.router.navigate(['error']);
        }
    }

    private inRole(role) {
        return _.includes(this.roles, role);
    }
}

HomeComponent 在登录后首次加载时,路由不会导航到例如“sites”路由,但奇怪的是它解决了siteSummaries 依赖项。第一次重定向失败后,我可以导航到另一条路线,然后尝试导航到“”路线,它正确地重定向到“站点”路线。

为什么初始导航不起作用?基于有关 navigate() 不起作用的其他类似问题,我尝试将路线更改为“/sites”和“./sites”,但无济于事。

更新 看起来它与解决路由的依赖关系有关。如果重定向到我的redirect() 函数中的“错误”路由,它会第一次成功。如果我将resolve 添加到我的“错误”路线,它第一次无法导航到它。奇怪的是,它通过 HTTP 调用来满足依赖关系。这是不等待navigate() 的承诺返回的问题吗?

更新 2 以下是要求的课程:

export class SiteIndexComponent implements OnInit {

    public siteSummaries: any;
    public totalRegisteredCount: number;
    public totalscreenFailedCount: number;
    public totalinProgressCount: number;

    constructor(private route: ActivatedRoute) { }

    ngOnInit() {
        this.siteSummaries = this.route.snapshot.data['siteSummaries'];
        this.totalRegisteredCount = this.getTotal('registeredCount');
        this.totalscreenFailedCount = this.getTotal('screenFailedCount');
        this.totalinProgressCount = this.getTotal('inProgressCount');
    }

    private getTotal(prop): number {
        var total = 0;
        _.forEach(this.siteSummaries, function (summary) {
            return total += summary[prop];
        });
        return total;
    }
}

@Injectable()
export class SiteSummariesResolve implements Resolve<any> {

    constructor(private sitesService: SitesService) { }

    resolve(route: ActivatedRouteSnapshot) {
        return this.sitesService.getSiteSummaries();
    }
}

getCurrentUser(): any {
    var currentUser = sessionStorage.getItem('currentUser');
    if (!currentUser) {
        return null;
    }
    return JSON.parse(currentUser);
}

更新 3 我把它扔进了我的app.component

private navigationInterceptor(event: RouterEvent): void {
    if (event instanceof NavigationStart) {
        console.log('started: ' + JSON.stringify(event));
    }
    if (event instanceof NavigationEnd) {
        console.log('ended: ' + JSON.stringify(event));
    }
    if (event instanceof NavigationCancel) {
        console.log('cancelled:' + JSON.stringify(event));
    }
    if (event instanceof NavigationError) {
        console.log('error:' + JSON.stringify(event));
    }
}

在路由加载失败的时候(第一次),先有一个 NavigationStart 的事件实例,然后是一个 NavigationCancel 的实例。以下是 NavigationCancel 上的事件:{"id":2,"url":"/sites","reason":""}。如您所见,没有给出任何理由...

【问题讨论】:

  • getCurrentUser 是异步操作吗?
  • 您的路由可能没问题。你能分享一下SiteIndexComponentSiteSummariesResolve吗?
  • @MezoIstvan 更新
  • @DeborahK 不,只是从sessionStorage 拉取。我更新了问题以包含它。

标签: angular angular2-routing


【解决方案1】:

我仍然不知道为什么它取消了我的路线导航,但我想出的解决方法是将 ngInit 更改为以下内容:

ngOnInit() {
    var currentUser = this.authService.getCurrentUser();
    this.roles = currentUser.roles;
    var that = this;
    setTimeout(function () { that.redirect(); }, 50);
}

在超时中包装我的重定向调用可以让事情按预期工作,除了难以察觉的延迟。这似乎是某种时间问题?如果我尝试将超时设置为 20,它也不起作用。

【讨论】:

  • 使用这种方法我得到ERROR TypeError: this.redirect is not a function,即使我定义了它并像这样使用它:private redirect(path: string): void
  • @An-droid 注意that = this
  • 当我尝试在 CustomErrorHandler... 中导航时,这个 setTimeout 变通方法对我有用。
  • 我遇到了同样的问题。我编写了一个自定义解析器,将传入的哈希转换为路径,并且重定向在除一个路径之外的所有路径上持续触发。我同意这可能是一些棘手的时间问题。如果 router.navigate 因触发时间过长而被拦截,setTimeout 会将其推送到事件队列中以异步触发。
【解决方案2】:

你不应该在构造函数中做有副作用的事情。相反,实现 ngOnInit:

class HomeComponent implements OnInit {
  ngOnInit() {
    // navigate things...
  }
}

另请参阅:Difference between Constructor and ngOnInit

【讨论】:

  • 提示:您可以尝试通过使用硬编码的目标路由进行调试来消除重定向逻辑内部失败的机会。
  • 可以确认。如果使用 ngOnInit 也会出现同样的问题。
【解决方案3】:

试试这个路由

import { Routes, RouterModule } from '@angular/router';


export const router: Routes = [
   { path: '',  redirectTo: 'main', pathMatch: 'full'},
  { path: 'main', component:AdminBodyComponent  },
  { path: 'admin', component:AdminComponent  },
  { path: 'posts',component:PostsComponent},
  { path: 'addposts',component:AddPostComponent}];

export const routes: ModuleWithProviders = RouterModule.forRoot(router);
step2:
inject into your .ts file
constructor(
  private router:Router,
  ...
)
step3:
this.router.navigate(['/addposts']);

【讨论】:

  • 请解释为什么这个代码示例解决了这个问题。
猜你喜欢
  • 1970-01-01
  • 2020-05-21
  • 2013-10-16
  • 2010-11-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多