【问题标题】:How to get query parameters from URL in Angular 5?如何从 Angular 5 中的 URL 获取查询参数?
【发布时间】: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}

标签: angular typescript angular-routing


【解决方案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 并获得 queryParams 或 queryParamMap 的任何“技巧”都对我不起作用。他们总是空着。

                我的 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

                    【讨论】:

                    【解决方案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

                    【讨论】:

                      猜你喜欢
                      • 2018-05-29
                      • 2016-06-11
                      • 2020-12-10
                      • 2021-11-09
                      • 1970-01-01
                      • 1970-01-01
                      • 2018-05-18
                      • 2018-07-22
                      • 2016-06-25
                      相关资源
                      最近更新 更多