如何从Angular 2中的url获取查询参数?


237

我使用angular2.0.0-beta.7。将组件加载到类似路径的路径上时/path?query=value1,会将其重定向到/path。为什么要删除GET参数?如何保存参数?

我的路由器有错误。如果我有一条主要路线

@RouteConfig([
  {
      path: '/todos/...',
      name: 'TodoMain',
      component: TodoMainComponent
  }
])

我的孩子路线像

@RouteConfig([
  { path: '/', component: TodoListComponent, name: 'TodoList', useAsDefault:true },
  { path: '/:id', component: TodoDetailComponent, name:'TodoDetail' }
])

那么我就无法在TodoListComponent中获取参数。我能够得到

params("/my/path;param1=value1;param2=value2") 

但我要经典

query params("/my/path?param1=value1&param2=value2")

1
您如何指定@RouteConfigpath
Pankaj Parkar '16

我发现错误。我有主路径和子路径,如果我有主路径,例如{路径:'/ todos / ...',名称:'TodoMain',组件:TodoMainComponent}和子路径{路径:'/',组件:TodoListComponent, name:'TodoList',useAsDefault:true},它不起作用,并且在没有查询参数的情况下无法重定向到url。
FireGM '16

Answers:


412

通过注入一个实例,ActivatedRoute可以订阅各种可观察对象,包括queryParamsparams

import {Router, ActivatedRoute, Params} from '@angular/router';
import {OnInit, Component} from '@angular/core';

@Component({...})
export class MyComponent implements OnInit {

  constructor(private activatedRoute: ActivatedRoute) {}

  ngOnInit() {
    // Note: Below 'queryParams' can be replaced with 'params' depending on your requirements
    this.activatedRoute.queryParams.subscribe(params => {
        const userId = params['userId'];
        console.log(userId);
      });
  }

}

关于取消订阅的注意事项

@Reto和@ codef0rmer正确地指出,根据官方文档,在这种情况下,不需要在unsubscribe()components onDestroy()方法内部。这已从我的代码示例中删除。(见蓝色警告框这个教程中的)


2
我还建议在这种特殊情况下,用承诺替换订购。this.activatedRoute.params.toPromise().then(响应=> ...).catch(错误=> ...);
2016年

我在哪里可以传递“ activatedRoute”?
michali '16

20
根据官方文档: 我需要退订吗? The Router manages the observables it provides and localizes the subscriptions. The subscriptions are cleaned up when the component is destroyed, protecting against memory leaks, so we don't need to unsubscribe from the route params Observable.
Reto

角度重定向而不触发订阅(或承诺)。我可以看到带有令牌的原始oAUth回调,但是随后它重定向到了没有查询参数的路由,console.log(param)只是一个空对象。
FlavorScape

1
@Sobhan,是的,有区别。switchMap运算符返回Observable,而subscribe运算符允许观察者(我们的组件)查看Observable最终发出的项目。因此,在文档中使用了2个switchmap实例。1)他们使用switchMap追加了对英雄的请求。与订阅不同,SwitchMap将确保如果用户在仍在检索英雄的同时重新导航到该路线,则该请求将被取消。2)使用了异步管道。异步管道消耗了一个可观察的对象,因此一定不能订阅(异步管道将为您完成此操作)。
斯蒂芬·保罗

103

当这样的URL http://stackoverflow.com?param1=value

您可以通过以下代码获取param1:

import { Component, OnInit } from '@angular/core';
import { Router, ActivatedRoute, Params } from '@angular/router';

@Component({
    selector: '',
    templateUrl: './abc.html',
    styleUrls: ['./abc.less']
})
export class AbcComponent implements OnInit {
    constructor(private route: ActivatedRoute) { }

    ngOnInit() {
        // get param
        let param1 = this.route.snapshot.queryParams["param1"];
    }
}

2
这是否意味着您不再需要在routeconfig路径中添加“ /:id”?因为当我使用它时我得到“未定义”,所以我在某个地方仍然会有错误
Axelle 18'1

2
大。这是我正在寻找的,因为我需要直接从动态服务器URL中读取参数。我不能使用导航。
The.Bear

37

即使该问题指定了beta 7版本,该问题也将作为Google上针对诸如angular 2查询参数之类的常用短语的搜索结果而出现。因此,这是最新路由器的答案(当前在alpha.7中)。

读取参数的方式发生了巨大变化。首先,您需要注入Router在构造函数参数中调用的依赖项,例如:

constructor(private router: Router) { }

然后我们可以在我们的ngOnInit方法上订阅查询参数(构造函数也可以,但是ngOnInit应该用于可测试性),例如

this.router
  .routerState
  .queryParams
  .subscribe(params => {
    this.selectedId = +params['id'];
  });

在此示例中,我们从类似的URL中读取查询参数IDexample.com?id=41

还有几件事要注意:

  1. 存取paramslike之类的属性params['id']总是返回一个字符串,可以通过在字符串前面加上前缀将其转换为数字+
  2. 以可观察的方式获取查询参数的原因是,它允许重新使用相同的组件实例,而不是加载新的实例。每次更改查询参数时,都会引起一个我们已订阅的新事件,因此我们可以对更改做出相应的反应。

有没有办法让多个参数传递给同一成员?例如,我想要'id'或'identification'转到this.selectedId。
phandinhlan

@phandinhlan:嗯,这并不是与Angular 2有关的问题。它当然可以实现,但是您需要自己定义逻辑。基本上,您要做的是先检查是否定义了第一个键,然后才从中读取值,如果没有,则使用另一个键读取值。这可以通过类似的方法来实现if (params.hasOwnProperty('id')) { this.selectedId = params['id'] } else { this.selectedId = params['identification']}
Roope Hakulinen '16

是的,我最终做了这样的事情。我只是认为会有某种“内置”方式,例如:this.selectedId = + params ['id']; this.selectedId = + params ['identification']; 当然,这没有任何意义,也行不通。
phandinhlan

28

我真的很喜欢@StevePaul的回答,但是我们可以这样做,而无需多余的订阅/取消订阅呼叫。

import { ActivatedRoute } from '@angular/router';
constructor(private activatedRoute: ActivatedRoute) {
    let params: any = this.activatedRoute.snapshot.params;
    console.log(params.id);
    // or shortcut Type Casting
    // (<any> this.activatedRoute.snapshot.params).id
}

7
当然,需要注意的是,它将是初始值,后续更改不会得到反映。因此,如果您要作为逻辑的一部分以编程方式更改URL参数,则需要注意这一点
含糊其词性:

不知道这是否会随Angular的更高版本而改变,但是我现在在this.activatedRoute.snapshot.queryParams中看到它
Michael

21

发送查询参数

import { Router } from '@angular/router';
this.router.navigate([ '/your-route' ], { queryParams: { key: va1, keyN: valN } });

接收查询参数

import { ActivatedRoute } from '@angular/router';
this.activatedRoute.queryParams.subscribe(params => {
    let value_1 = params['key'];
    let value_N = params['keyN'];
});

官方资料


读取效果很好,但是区分大小写。如何使它不区分大小写?
Unnie

12

嗨,您可以使用URLSearchParams,您可以在此处了解更多信息

进口:

import {URLSearchParams} from "@angular/http";

和功能:

getParam(){
  let params = new URLSearchParams(window.location.search);
  let someParam = params.get('someParam');
  return someParam;
}

注意:并非所有平台都支持它,并且由角度文档似乎处于“ EXPERIMENTAL”状态


2
这对我不起作用。我发现window.location.search包含querystring参数的前导问号。因此,第一个参数的键将带有问号。
AJ莫里斯

AJ莫里斯(AJ Morris),解决您的问题: if (window.location.search.indexOf('?') == 0){ normalizedQueryString = window.location.search.substring(1); } else { normalizedQueryString = window.location.search; } let params = new URLSearchParams(normalizedQueryString);
歧义的

URLSearchParams已弃用。现在,您可以使用ActivatedRoute做到这一点。
罗伯特·布拉斯科·维拉罗亚

7

首先,我发现使用Angular2的原因是带有查询字符串的url为 /path;query=value1

要在组件中访问它,请使用,这样,但是现在遵循一个代码块:

    constructor(params: RouteParams){
    var val = params.get("query");
    }

至于为什么在加载组件时将其删除,这不是默认行为。我专门在一个干净的测试项目中进行了检查,但没有重定向或更改。它是默认路由还是其他关于路由的特殊功能?

在Angular2教程中了解有关使用查询字符串和参数进行路由的信息,网址https://angular.io/docs/ts/latest/guide/router.html#!#query-parameters


我无法使用“; param1 = value1; param2 = value2”之类的参数,此链接在另一个网站上生成,并在我的网站上重定向,例如“ example.com/auth?code_for_auth=askjfbkajdsbfksajdf”
FireGM 2016年

目前,在Angular2中设置路由的方式确实不可行。由于子路由确实取决于矩阵URL,因此将需要某种解决方法。至少据我所知。我会在我的网络服务器上拦截它,并将其转换为hack,很烂,但目前我想不出另一种方式
Namirna,2016年

您无法要求链接网站更改其网址吗?
Namirna '16

1
不,但是我解决了这个问题,只需手动解析Location.path()
FireGM,2016年

4
此解决方案已弃用!

7

您可以使用ActivatedRoute在URL中传递时获取查询参数,如下所示:-

网址:http://domain.com?test = abc

import { Component } from '@angular/core';
import { ActivatedRoute }     from '@angular/router';

@Component({
  selector: 'my-home'
})
export class HomeComponent {

  constructor(private sharedServices : SharedService,private route: ActivatedRoute) { 
    route.queryParams.subscribe(
      data => console.log('queryParams', data['test']));
  }

}

7

获取URL参数作为对象。

import { Router } from '@angular/router';
constructor(private router: Router) {
    console.log(router.parseUrl(router.url));
}

2

如果只想获取一次查询参数,则最好的方法是使用take方法,因此您不必担心取消订阅。这是简单的代码段:

constructor(private route: ActivatedRoute) {
  route.snapshot.queryParamMap.take(1).subscribe(params => {
     let category = params.get('category')
     console.log(category);
  })
}

注意:如果以后要使用参数值,删除take(1)


2

现在它是:

this.activatedRoute.queryParams.subscribe((params: Params) => {
  console.log(params);
});

1
感谢您提供此代码段,它可能会提供一些有限的短期帮助。通过说明为什么这是一个解决问题的好方法,适当的解释将大大提高其长期价值,对于其他有类似问题的读者来说,这样做将更为有用。请编辑您的答案以添加一些解释,包括您所做的假设
Shawn C.

1

我希望它会帮助别人。

上面的问题指出,页面重定向后需要查询参数值,并且我们可以假定快照值(不可观察的替代方案)就足够了。

这里没有人提到官方文档中有关snapshot.paramMap.get的内容

this.route.snapshot.paramMap.get('id')

因此,在发送之前,请将其添加到发送/重定向组件中:

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

然后按照以下任一方法进行重定向(在此处记录):

this.router.navigate(['/heroes', { id: heroId, foo: 'foo' }]);

或者简单地:

this.router.navigate(['/heroes', heroId ]);

确保你有你的路由模块中添加了这个如记录在这里

 { path: 'hero/:id', component: HeroDetailComponent }

最后,在您需要使用查询参数的组件中

  • 添加导入(在此处记录):

    import { Router, ActivatedRoute, ParamMap } from '@angular/router';
  • 注入ActivatedRoute

(文档还导入了switchMap,还注入了Router和HeroService -但它们仅在可观察的替代方案中才是必需的-当您像本例一样使用快照替代方案时,则不需要它们):

    constructor(
      private route: ActivatedRoute
    ) {}
  • 并获得所需的值(在此处记录):

    ngOnInit() {
      const id = this.route.snapshot.paramMap.get('id');
    }

注意:如果将路由模块添加到功能模块(如文档中所示),请确保在APP.MODULE.ts中将路由模块引入IMPORTS中的AppRoutingModule(或其他具有根级应用程序路由的文件)之前:[]。否则将找不到其他功能路由(因为它们将在{path:'**',redirectTo:'/ not-found'}之后出现,并且您只会看到未找到的消息)。


1

您只需要在构造函数中注入ActivatedRoute,然后通过它访问params或queryParams

constructor(private route:ActivatedRoute){}
ngOnInit(){
        this.route.queryParams.subscribe(params=>{
        let username=params['username'];
      });
 }

在某些情况下,它在NgOnInit中不提供任何信息...可能是由于在初始化参数之前进行了init调用,在这种情况下,您可以通过使用函数debounceTime(1000)要求observable等待一段时间来实现此目的

例如=>

 constructor(private route:ActivatedRoute){}
    ngOnInit(){
            this.route.queryParams.debounceTime(100).subscribe(params=>{
            let username=params['username'];
          });
     }

debounceTime()仅在经过特定的时间间隔后才发出可观察到的源值,而没有其他源发出


0

如果未在路由中定义参数,则无法从RouterState获取参数,因此在您的示例中,您必须解析查询字符串...

这是我使用的代码:

let re = /[?&]([^=#&]+)=([^&#]*)/g;
let match;
let isMatch = true;
let matches = [];
while (isMatch) {
    match = re.exec(window.location.href);
    if (match !== null) {
        matches[decodeURIComponent(match[1])] = decodeURIComponent(match[2]);
        if (match.index === re.lastIndex) {
            re.lastIndex++;
        }
    }
    else {
        isMatch = false;
    }
}
console.log(matches);


0

查询和路径(角度8)

如果您有类似https://myapp.com/owner/123/show?height=23的网址,使用

combineLatest( [this.route.paramMap, this.route.queryParamMap] )
  .subscribe( ([pathParams, queryParams]) => {
    let ownerId = pathParams.get('ownerId');    // =123
    let height  = queryParams.get('height');    // =height
    // ...
  })

更新

如果您使用this.router.navigate([yourUrl]);并且查询参数嵌入yourUrl字符串中,则angular对URL进行编码,并且得到类似https://myapp.com/owner/123/show%3Fheight%323的内容 -上述解决方案将产生错误的结果( queryParams将为空,并且查询参数可以粘贴到最后一个路径参数(如果它在路径末端)。在这种情况下,将导航方式更改为此

this.router.navigateByUrl(yourUrl);
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.