首页 文章

Angular2路由器保持查询字符串

提问于
浏览
35

我写了一个使用路由器的Angular2(v2.0.1)应用程序 . 该网站加载了几个查询字符串参数,因此完整的URL最初如下所示:

https://my.application.com/?param1=val1&param2=val2&param3=val3

在我的路由配置中,我有一个重定向空路由的条目:

const appRoutes: Routes = [
    {
        path: '',
        redirectTo: '/comp1',
        pathMatch: 'full'
    },
    {
        path: 'comp1',
        component: FirstComponent
    },
    {
        path: 'comp2',
        component: SecondComponent
    }
];

我的问题是,在应用程序被引导后,URL不再包含查询参数,而是看起来像这样:

https://my.application.com/comp1

有没有什么办法可以配置路由器,以便在导航时保留初始查询字符串?

谢谢
卢卡斯

8 回答

  • 0

    我认为在路由配置中没有办法定义它 .

    目前,它支持 routerLink 和启用命令式导航

    您可以在空路径路径中添加一个保护,在保护导航到 /comp1 路径的地方完成 .

    router.navigate(['/comp1'], { preserveQueryParams: true }); //deprecated see update note
    
    router.navigate(['/comp1'], { queryParamsHandling: "merge" });
    

    有一个PR允许全局配置 preserveQueryParams .

    更新说明:从https://angular.io/api/router/NavigationExtras开始,不推荐使用preserveQueryParams,而是使用queryParamsHandling

  • 0

    如果您使用HTML模板进行导航,则可以使用

    <a [routerLink]="['/page-2']" [routerLinkActive]="['is-active']" queryParamsHandling="merge">
    

    需要注意的是queryParamsHandling参数没有方括号 .

  • 2

    GünterZöchbauer的答案应该正常,但由于某种原因,它根本不适合我 . 最终工作的是直接传递 queryParams 而不是'preserving' .

    这就是我的后卫的样子:

    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
        (...)
        this.router.navigate(['login'], { queryParams: route.queryParams });
    }
    
  • 32

    您可能想要搜索https://github.com/angular/angular/issues以获取与此类似的功能请求 . 如果不存在,请提交功能请求 .

    同时:我相信你需要在路径上创建一个组件:'',其唯一目的是在保留QueryString参数的同时重定向到'/ comp1' .

  • 26

    捕获-base href-中的原始URL

    https://example.com/order?id=123

    那么它会坚持下去

    https://example.com/order?id=123#/product

  • 6

    如果您使用HTML模板导航,也可以使用 preserveQueryParams="true"

    请注意 preserveQueryParams 没有方括号 .

    例如:

    <a [routerLink]="['/navigate-to']" preserveQueryParams="true">

  • 0

    有一种使用辅助路由的解决方法,因为Angular将在主路由导航中保留这些路由 .

    首先,在顶部组件中添加一个命名路由器插座:

    <router-outlet name="params"><router-outlet>
    

    接下来,创建一个虚拟组件以路由到:

    @Component({
        template: ""
    })
    export class ParamsComponent {}
    

    并定义一个路由以将此组件实例化到指定的插座:

    {
        path: ':val1',
        component: ParamsComponent,
        outlet: "params"
    }
    

    将您的应用导航更改为:

    https://my.application.com/(params:val1)

    如果您查看任何ActivatedRoute,您可以使用以下命令找到“params”路线:

    var paramsRoute = this.activatedRoute.route.children.find(r => r.outlet == "params");
    

    如果paramsRoute为null,则url不包含(params:val1) .

    由于辅助路由在初始加载后的主路由之后被实例化,因此下一部分有点“hacky” . 因此,在您的应用程序完全加载之前,您可能会发现paramsRoute.snapshot为null . 有一个私有属性“_futureSnapshot”,它将包含初始启动时的路径参数...并在应用程序的生命周期中持续存在 . 您可以通过以下方式使用以下内容:

    var queryParams = 
          paramsRoute
          ? paramsRoute["_futureSnapshot"].params
          : {};
    var val1 = queryParams["val1"];
    

    鉴于_futureSnapshot不是公共API的一部分,这可能是我们不应该使用的字段 . 如果您觉得使用它很苛刻,您可能订阅了paramsRoute.params,但这可能会使您的组件复杂化 .

    if (paramsRoute) {
        paramsRoute.params.subscribe(params => {
            this.queryParams = params;
            this.loadData();
        });
    } else {
        this.queryParams = {};
        this.loadData();
    }
    

    =========修正=============

    我找到了一种更好的方法来提取查询参数,这绝对不是很icky ...在路由发生之前实例化的组件或服务中,添加以下逻辑:

    const routeRecognizedSubscription = this.router.events
            .filter(e => e instanceof RoutesRecognized)
            .subscribe((e: RoutesRecognized) => {
                const paramsRoute = e.state.root.children.find(r => r.outlet == "params");
                if (paramsRoute) {
                    // capture or use paramsRoute.params 
                }
                routeRecognizedSubscription.unsubscribe();
            });
    

    此代码临时订阅在导航之前发生的RoutesRecognized事件 . 收到第一个事件后,它会自动取消订阅,因为我们只需要在应用启动时执行此操作 .

    在第一个事件中,我们寻找对应于“params”出口的状态 . 如果找到,params属性将包含我们需要的数据 . 无需访问私有 property .

  • 0

    事实证明,没有其他黑客攻击的无证方法是简单地删除“redirectTo”字段中的前导斜杠 . 由于您匹配完整路径,您可以确定它将执行您想要的操作(即没有惊喜的URL段),并且由于它不再是绝对目标,因此Angular将保留当前查询参数 .

    所以在这种情况下

    {
      path: '',
      redirectTo: '/comp1',
      pathMatch: 'full'
    }
    

    变为:

    {
      path: '',
      redirectTo: 'comp1',
      pathMatch: 'full'
    }
    

    资料来源:https://github.com/angular/angular/issues/13315

相关问题