Angular2路由器保留查询字符串


78

我编写了一个使用路由器的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

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

谢谢
卢卡斯

Answers:


65

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

目前支持routerLinks和命令式导航以启用

您可以将保护添加到空路径路由,在保护路径中导航到该/comp1路径。

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

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

更新说明:从https://angular.io/api/router/NavigationExtras出发,不建议使用reserveQueryParams,而应使用queryParamsHandling


1
该行代码将添加到哪里?您可以用代码示例解释“后卫”吗?
mattrowsboats17年

我这样做了,但是没有将canActivate防护添加到空字符串“重定向”路由中。
mattrowsboats17年

2
好的,但是在输入应用程序时问题仍然存在。如果您试图在应用程序启动后“捕获” URL参数,那就为时已晚。他们已经被剥夺了。
mattrowsboats17年

1
长时间后,我发现这navigateByUrl行不通。最好navigate始终使用。
Karthik

1
不好意思,但我只有AArias回答对我有用(角度9,如果相关的话)。
Arnaud P

50

如果您使用HTML模板浏览,则可以使用

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

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


1
这是最好的答案,关于括号的评论确实为我节省了一些时间
阿拉

HTML解决方案是我真正想要的。谢谢!
Dinesh Shekhawat

17

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

所以在这种情况下

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

变成:

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

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


搞定了!那是唯一的方式
Yazan Khalaileh,

最直接的答案
里卡多

12

GünterZöchbauer的答案应该可以正常工作,但是由于某种原因,它根本不适合我。最终的工作是queryParams直接传递而不是“保留”它们。

这是我的警卫的样子:

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

是的,这个答案也是唯一对我
有用的


1

经过最多的回答后,我发现

  • GünterZöchbauer的答案对我根本不起作用
  • 克里斯托弗(Christopher)提出的取消领导的建议/也没有做到
  • AArias的回答确实有效,但导致历史记录中添加了两个网址:
    1. https://my.application.com/comp1?param=val <=(ಠ益ಠ)
    2. https://my.application.com/comp1;param=val

因此,这是另一种方法,最终表现出了我的期望:

import { ActivatedRoute, Router } from '@angular/router';

class Component {
    constructor(private route: ActivatedRoute, private router: Router) {}

    someMethod() {
        router.navigate(['/comp1', this.route.snapshot.params]);
    }
}


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,则网址不包含(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();
}

=========修改=============

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

    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属性将包含我们需要的数据。无需访问私有财产。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.