如何从 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 对我不起作用。 @RomeoProfijtparamMap
用于路由中的参数,而不是查询参数。如果您的路线定义为/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¶m2=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&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>
之前添加<router-outlet><router-outlet>
在此之前,请确保您已在 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¶m2=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
【讨论】:
这不是真的:请参阅 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 的 HTTP 发布请求中传递 url 中的查询参数
如何从 getInitialProps 中的 url 获取查询参数?