Angular2路由器保持查询字符串

时间:2016-10-06 14:27:07

标签: angular angular2-routing

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

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

谢谢你 卢卡斯

10 个答案:

答案 0 :(得分:46)

我不认为有一种方法可以在路线配置中定义它。

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

您可以在空路径路线中添加一个警卫,在/comp1路线的警卫导航中完成。

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

允许preserveQueryParams全局配置PR

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

答案 1 :(得分:34)

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

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

值得注意的是queryParamsHandling param没有方括号。

答案 2 :(得分:7)

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

这就是我的警卫的样子:

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

答案 3 :(得分:4)

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

所以在这种情况下

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

成为:

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

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

答案 4 :(得分:2)

您可能希望在https://github.com/angular/angular/issues中搜索与此类似的功能请求。如果不存在,请提交功能请求。

同时:我相信您需要在路径上创建一个组件:&#39;&#39;&#39;&#39;,其唯一目的是重定向到&#39; / comp1&#39;同时保留QueryString参数。

答案 5 :(得分:1)

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

  • GünterZöchbauer的答案对我根本不起作用
  • 克里斯托弗删除前导/的建议也没有做到
  • 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]);
    }
}

答案 6 :(得分:0)

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

请注意preserveQueryParams没有方括号。

例如:

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

答案 7 :(得分: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,则可以使用以下方法找到“参数”路由:

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

答案 8 :(得分:0)

在 Angular 10 中,您现在可以使用如下:

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

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

    someMethod() {
        //You can use either merge or preserve to keep the query params
        this.router.navigate(['/'], { queryParamsHandling: 'preserve' })

    }
}

 

答案 9 :(得分:-1)

在-base href中捕获原始网址 -

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

然后它会坚持

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