如何从 Angular 5 中的 URL 获取查询参数?

Posted

技术标签:

【中文标题】如何从 Angular 5 中的 URL 获取查询参数?【英文标题】:How to get query parameters from URL in Angular 5? 【发布时间】:2018-05-07 10:24:11 【问题描述】:

我正在使用 Angular 5.0.3,我想使用一堆查询参数(如 /app?param1=hallo&param2=123)来启动我的应用程序。 How to get query params from url in Angular 2? 中给出的每个提示都对我不起作用。

知道如何让查询参数起作用吗?

private getQueryParameter(key: string): string 
  const parameters = new URLSearchParams(window.location.search);
  return parameters.get(key);

这个私有函数可以帮助我获取参数,但我认为在新的 Angular 环境中这不是正确的方法。

[更新:] 我的主应用看起来像

@Component(...)
export class AppComponent implements OnInit 

  constructor(private route: ActivatedRoute) 

  ngOnInit(): void 
    // would like to get query parameters here...
    // this.route...
  

【问题讨论】:

你在使用路由器吗?网址来自哪里? 是的,有一个 ActivatedRoute。我更新了我的问题以显示我的主要组件的外观。 你能告诉我你的路线常数,你在哪里设置了所有路线吗? const appRoutes: Routes = [ path: "one", component: PageOneComponent, path: "", redirectTo: "/one", pathMatch: "full", path: " **", redirectTo: "/one" ];我的路线常数。我想将主应用程序中的所有参数存储在 DTO 中,然后导航到另一个页面。页面导航按预期工作,但我只能通过我的“getQueryParameter”函数在 main 处获取查询参数。我意识到在你的问题中存在我忘记的东西。我需要在任何地方标记我的参数名称吗? 是的,在您的路线中,您还需要定义参数。如果您查看 angular.io 上的路由文档,您可以看到它们如何在特定路由上定义参数。像这样 path: 'abc/:param1', component: componentClassName 【参考方案1】:

在 Angular 5 中,通过订阅 this.route.queryParams 来访问查询参数(请注意,更高的 Angular 版本 recommend queryParamMap,另请参阅其他答案)。

示例:/app?param1=hallo&param2=123

param1: string;
param2: string;
constructor(private route: ActivatedRoute) 
    console.log('Called Constructor');
    this.route.queryParams.subscribe(params => 
        this.param1 = params['param1'];
        this.param2 = params['param2'];
    );

而路径变量由this.route.snapshot.params访问

示例:/param1/:param1/param2/:param2

param1: string;
param2: string;
constructor(private route: ActivatedRoute) 
    this.param1 = this.route.snapshot.params.param1;
    this.param2 = this.route.snapshot.params.param2;

【讨论】:

根据 Angular 6 docs,不鼓励使用 ActivatedRoute.queryParams 和 .params 并且可能在未来的版本中被弃用;见更新here @ShubhenduVaid 解释为什么,他们应该使用 ngOnInit 而不是构造函数。最佳实践是使用 RxJS observable,然后在使用 observables 时使用声明式方法,然后在 html 上使用异步 按照你的例子 1. this.param1 在任何方法中都返回为空或未定义。有没有办法让这些值在整个班级中都可以访问。 谢谢。帮了大忙。【参考方案2】:

这对我来说是最干净的解决方案

import  Component, OnInit  from '@angular/core';
import  ActivatedRoute  from '@angular/router';

export class MyComponent 
  constructor(
    private route: ActivatedRoute
  ) 

  ngOnInit() 
    const firstParam: string = this.route.snapshot.queryParamMap.get('firstParamKey');
    const secondParam: string = this.route.snapshot.queryParamMap.get('secondParamKey');
  

【讨论】:

这很有帮助,谢谢。从 Angular 6.0.8 开始,我正在使用它,它适用于我:this.route.snapshot.queryParams["firstParamKey"] 这在 Angular8 中对我有用。 this.route.snapshot.queryParamMap 有效。 this.route.snapshot.paramMap 对我不起作用。 @RomeoProfijt paramMap 用于路由中的参数,而不是查询参数。如果您的路线定义为/myroute/:id 并导航到/myroute/45,那么您可以从paramMap.get('id') 获得45。【参考方案3】:

我知道 OP 要求 Angular 5 解决方案,但是对于所有偶然发现这个问题的人来说,对于更新的(6+)Angular 版本。引用Docs,关于 ActivatedRoute.queryParams (大多数其他答案都基于):

两个较旧的属性仍然可用。他们能力不如 他们的替代品,不鼓励,将来可能会被弃用 角度版本。

params — 一个包含必需和可选参数的 Observable 特定于路由的参数。请改用 paramMap。

queryParams — 一个包含可用查询参数的 Observable 到所有路线。请改用 queryParamMap。

根据Docs,获取查询参数的简单方法如下:

constructor(private route: ActivatedRoute)  

ngOnInit() 
    this.param1 = this.route.snapshot.paramMap.get('param1');
    this.param2 = this.route.snapshot.paramMap.get('param2');

有关更高级的方法(例如高级组件重用),请参阅this Docs 章节。

编辑:

正如它在下面的 cmets 中正确说明的那样,这个答案是错误的 - 至少对于 OP 指定的情况。

OP 要求获取全局查询参数 (/app?param1=hallo&param2=123);在这种情况下,您应该使用 queryParamMap (就像在@dapperdan1985 答案中一样)。

另一方面,paramMap 用于特定于路由的参数(例如 /app/:param1/:param2,导致 /app/hallo/123)。

感谢@JasonRoyle 和@daka 指出

【讨论】:

不应该使用queryParamMap 而不是paramMap 来获取查询字符串参数吗? @JasonRoyle 看来你是对的,paramMap 不起作用。 这个答案需要根据上面的 cmets 进行更正。 @JasonRoyle,daka,你是对的,谢谢你的指出。更正了答案。 找到完美的工作代码:jsonworld.com/blog/…【参考方案4】:

也可以使用HttpParams,如:

  getParamValueQueryString( paramName ) 
    const url = window.location.href;
    let paramValue;
    if (url.includes('?')) 
      const httpParams = new HttpParams( fromString: url.split('?')[1] );
      paramValue = httpParams.get(paramName);
    
    return paramValue;
  

【讨论】:

澄清一下,我有两个域指向不同的语言站点。 localhost/ --> En,localhost/?lang=fr --> 法语。我有路由:path: '', redirectTo: '/list' 。 this.route.snapshot 对我不起作用,因为它 redirectTo /list 消除了“lang”查询字符串。但这个解决方案对我有用。 作为@RyanHuang,我也有同样的问题。但这个解决方案在我的第一次试验中奏效了。 找到比上面更好的解决方案:jsonworld.com/blog/… 在编写单元测试时 httpParams.get(paramName) 无法获取值。你有什么想法我们可以如何做到这一点?【参考方案5】:

查询和路径参数(Angular 8)

对于像https://myapp.com/user/666/read?age=23 这样的网址使用

import  combineLatest  from 'rxjs';
// ...

combineLatest( [this.route.paramMap, this.route.queryParamMap] )
  .subscribe( ([pathParams, queryParams]) => 
    let userId = pathParams.get('userId');    // =666
    let age    = queryParams.get('age');      // =23
    // ...
  )

更新

如果您使用this.router.navigate([someUrl]); 并且您的查询参数嵌入在someUrl 字符串中,那么角度编码一个URL 并且您会得到类似https://myapp.com/user/666/read%3Fage%323 的内容 - 以上解决方案将给出错误结果(queryParams 将为空,如果路径参数位于路径末端,则路径参数可以粘合到最后一个路径参数)。在这种情况下改变导航方式to this

this.router.navigateByUrl(someUrl);

【讨论】:

感谢@Kamil Kiełczewski,你拯救了我的一天【参考方案6】:
import  ParamMap, Router, ActivatedRoute  from '@angular/router';

constructor(private route: ActivatedRoute) 

ngOnInit() 
    console.log(this.route.snapshot.queryParamMap);

更新

import  Router, RouterStateSnapshot  from '@angular/router';

export class LoginComponent 
    constructor(private router: Router) 
        const snapshot: RouterStateSnapshot = router.routerState.snapshot;
        console.log(snapshot);  // <-- hope it helps
    

【讨论】:

这似乎还不够,我得到了 ActivatedRouteSnapshot 但 queryParams 是一个空对象,params 也是空的,并且 .queryParamMap.get('name') 返回 null。看来 ngOnInit() 获取这样的查询参数还为时过早。 其实如果你想得到这个参数你应该改变你的路线。 我有大约 10 个不同顺序的参数。因此我必须使用命名查询参数。以及如何设置我的主要 AppComponent 以实现有 10 个参数。 url/myprogram?a=1&b=2&c=4... 接缝我有问题吗?我需要将每个参数路由到其他组件吗?我希望不会。 你试过这个吗? this.route.snapshot.queryParamMap @DmitryGrinko 将实体 ID 放入路由中并不是一个坏模式,它允许深度链接到详细视图。【参考方案7】:

它对我有用:

constructor(private route: ActivatedRoute) 

ngOnInit()

    this.route.queryParams.subscribe(map => map);
    this.route.snapshot.queryParams; 

查看更多选项How get query params from url in angular2?

【讨论】:

【参考方案8】:

不幸的是,最干净的解决方案并不是最可扩展的解决方案。在最新版本的 Angular 中,其他答案中建议您可以使用 ActivatedRoute Injectible 轻松获取查询参数,并专门利用快照属性:

this.route.snapshot.queryParamMap.get('param')

或 subscribe 属性(用于查询字符串将更新的情况,例如通过用户 ID 导航):

this.route.queryParamMap.subscribe(params => console.log(params));

我在这里告诉你,这些解决方案有一个巨大的缺陷,已经有一段时间没有解决了:https://github.com/angular/angular/issues/12157

总而言之,唯一的防弹解决方案是使用良好的老式香草 javascript。在这种情况下,我为 URL 操作创建了一个服务:

import  Injectable  from '@angular/core';
import  IUrl  from './iurl';

@Injectable()
export class UrlService 
    static parseQuery(url: string): IUrl 
        const query = url.slice(url.indexOf('?')+1).split('&').reduce( (acc,query) => 
            const parts = query.split('=');
            acc[parts[0]] = parts[1];
            return acc;
        , );

        return 
            a: query['a'],
            b: query['b'],
            c: query['c'],
            d: query['d'],
            e: query['e']
        
    

【讨论】:

【参考方案9】:

Angular Router 提供方法 parseUrl(url: string) 将 url 解析为 UrlTree。 UrlTree 的属性之一是 queryParams。所以你可以这样做:

this.router.parseUrl(this.router.url).queryParams[key] || '';

【讨论】:

请不要针对不同的问题发布多个相同的答案。关于这种做法有一些有用的建议here 如果您不需要处理 URL 更改,即参数已在当前 URL 中可用,请使用此选项。否则以可观察的方式进行。【参考方案10】:

当我在寻找类似的解决方案时偶然发现了这个问题,但我不需要完整的应用程序级路由或更多导入的模块之类的东西。

以下代码非常适合我的使用,不需要额外的模块或导入。

  GetParam(name)
    const results = new RegExp('[\\?&]' + name + '=([^&#]*)').exec(window.location.href);
    if(!results)
      return 0;
    
    return results[1] || 0;
  

  PrintParams() 
    console.log('param1 = ' + this.GetParam('param1'));
    console.log('param2 = ' + this.GetParam('param2'));
  

http://localhost:4200/?param1=hello&amp;param2=123 输出:

param1 = hello
param2 = 123

【讨论】:

【参考方案11】:

发现于:Parent components gets empty Params from ActivatedRoute

为我工作:

import Component, OnDestroy, OnInit from '@angular/core';
import  Router, ActivatedRoute, Params, RoutesRecognized  from '@angular/router';

@Component(
  selector: 'app-navigation-bar',
  templateUrl: './navigation-bar.component.html',
  styleUrls: ['./navigation-bar.component.scss']
)
export class NavigationBarComponent implements OnInit, OnDestroy 
  private sub: any;
  constructor(private route: ActivatedRoute, private router: Router) 

  ngOnInit() 
    this.sub = this.router.events.subscribe(val => 
      if (val instanceof RoutesRecognized) 
        console.log(val.state.root.firstChild.params);
      
    );
  

  ngOnDestroy() 
    this.sub.unsubscribe();
  


【讨论】:

【参考方案12】:

简单的解决方案

 // in routing file
       
            path: 'checkout/:cartId/:addressId',
            loadChildren: () => import('./pages/checkout/checkout.module').then(m => m.CheckoutPageModule)
          ,

    // in Component file

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

                 constructor(
                      private _Router: ActivatedRoute
                  )  

                  ngOnInit() 
                    this.cartId = this._Router.snapshot.params.cartId;
                    this.addressId = this._Router.snapshot.params.addressId;
                    console.log(this.addressId, "addressId")
                    console.log(this.cartId, "cartId")
                  

【讨论】:

【参考方案13】:

当你有一个空路由对象时,这主要是因为你没有在你的 app.component.html 中使用路由器插座。

没有这个,您将无法获得具有非空子对象的有意义的路由对象,尤其是 params 和 queryParams。

尝试在致电 <app-main-component></app-main-component>之前添加&lt;router-outlet&gt;&lt;router-outlet&gt;

在此之前,请确保您已在 app-routing > 中准备好查询参数,该参数导出 App 组件使用的类 Route:

param: '/param/:dynamicParam', path: MyMainComponent

当然,为了获得你的参数,我个人使用 this.route.snapshot.params.dynamicParam 其中 dynamicParam 是你的应用程序路由组件中使用的名称 :)

【讨论】:

【参考方案14】:

小心你的路线。 “redirectTo”将删除|删除任何查询参数。

const appRoutes: Routes [
 path: "one", component: PageOneComponent,
 path: "two", component: PageTwoComponent,
 path: "", redirectTo: "/one", pathMatch: full,
 path: "**", redirectTo: "/two"
]

我使用“/main?param1=a&param2=b”之类的查询参数调用我的主组件,并假设我的查询参数在重定向转发生效之前到达主组件中的“ngOnInit()”方法。

但这是错误的。重定向将在之前,删除查询参数并在没有查询参数的情况下调用主组件中的 ngOnInit() 方法。

我将路线的第三行改为

path: "", component: PageOneComponent,

现在我的查询参数可以在主要组件 ngOnInit 和 PageOneComponent 中访问。

【讨论】:

【参考方案15】:

只是偶然发现了同样的问题,这里的大多数答案似乎只解决了 Angular 内部路由,然后其中一些解决了与请求参数不同的路由参数。

我猜我的用例与 Lars 的原始问题类似。

对我来说,用例是例如推荐跟踪:

Angular 在mycoolpage.com 上运行,带有哈希路由,所以mycoolpage.com 重定向到mycoolpage.com/#/。但是,对于推荐,mycoolpage.com?referrer=foo 之类的链接也应该可用。不幸的是,Angular 立即剥离了请求参数,直接转到mycoolpage.com/#/

不幸的是,使用空组件 + AuthGuard 并获得 queryParamsqueryParamMap 的任何“技巧”都对我不起作用。他们总是空着。

我的 hacky 解决方案最终是在 index.html 的一个小脚本中处理这个问题,该脚本获取完整的 URL,with 请求参数。然后我通过字符串操作获取请求参数值并将其设置在窗口对象上。然后一个单独的服务处理从窗口对象获取 id。

index.html 脚本

const paramIndex = window.location.href.indexOf('referrer=');
if (!window.myRef && paramIndex > 0) 
  let param = window.location.href.substring(paramIndex);
  param = param.split('&')[0];
  param = param.substr(param.indexOf('=')+1);
  window.myRef = param;

服务

declare var window: any;

@Injectable()
export class ReferrerService 

  getReferrerId() 
    if (window.myRef) 
      return window.myRef;
    
    return null;
  

【讨论】:

【参考方案16】:
/*
Example below url with two param (type and name) 
URL : http://localhost:4200/updatePolicy?type=Medicare%20Insurance&name=FutrueInsurance
*/ 
  constructor(private route: ActivatedRoute) 
    //Read url query parameter `enter code here`
  this.route.queryParams.subscribe(params => 
    this.name= params['type'];
    this.type= params['name'];
    alert(this.type);
    alert(this.name);

 );

  

【讨论】:

【参考方案17】:

在,我认为 Angular 8:

ActivatedRoute.params 已替换为 ActivatedRoute.paramMap ActivatedRoute.queryParams 已替换为 ActivatedRoute.queryParamMap

【讨论】:

这不是真的:请参阅 v8.angular.io/api/router/ActivatedRoute 了解 Angular 8 和此处了解当前 Angular 10:angular.io/guide/router#activated-route。 ActivatedRoute 具有所有四个属性。【参考方案18】:

如果您不使用 Angular 路由器,请尝试 querystring。安装它

npm install --save querystring

到您的项目。在你的组件中做这样的事情

import * as qs from 'querystring';
...
ngOnInit() 
   const params = qs.parse(window.location.search.substring(1));
   ...

substring(1) 是必要的,因为如果您有类似 '/mypage?foo=bar' 的内容,那么密钥名称将是 ?foo

【讨论】:

以上是关于如何从 Angular 5 中的 URL 获取查询参数?的主要内容,如果未能解决你的问题,请参考以下文章

如何从 Angular 5 中的 url 下载 pdf 文件

尝试从 Angular 5 中的 JSON 递归获取键值

如何在 Angular 的 HTTP 发布请求中传递 url 中的查询参数

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

Angular 5 无法从 HttpXsrfTokenExtractor 获取 XSRF 令牌

如何从 Swift 3 xcode8 的 UIWebView 中的 url 获取查询字符串参数?