如何从 Angular 2 中的 url 获取查询参数?
Posted
技术标签:
【中文标题】如何从 Angular 2 中的 url 获取查询参数?【英文标题】:How to get query params from url in Angular 2? 【发布时间】:2016-06-11 19:33:56 【问题描述】:我使用 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¶m2=value2")
【问题讨论】:
你如何为这个path
指定@RouteConfig
?
我发现了错误。我有主路由和子路由,如果我有主路由 path: '/todos/...', name: 'TodoMain', component: TodoMainComponent 和子路由 path: '/', component: TodoListComponent, name: 'TodoList', useAsDefault:true ,它不起作用并重定向到没有查询参数的 url。
【参考方案1】:
当一个 URL 是这样的 http://***.com?param1=value
您可以通过以下代码获取参数1:
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"];
【讨论】:
这是否意味着您不再需要在routeconfig路径中添加“/:id”?因为当我使用它时我得到“未定义”,所以我必须在某个地方仍然有错误 太棒了。这是我正在寻找的,因为我需要直接从动态服务器 url 读取参数。我无法使用导航。 我不确定为什么quearyParams
是
,即使在ngOnInit()
上我也对this.activatedRoute.queryParams.subscribe((params) => console.log(params))
进行了更改,它开始正常工作.. 我不确定这是否是正确的方法做吧
啊.. 我知道为什么它是undefined
,我以前没有使用<router-outlet>
,因为只有一个组件。现在我添加了一些路线并从快照中检查queryParamMap
是否可用。认为这对将来的某人有帮助【参考方案2】:
我的老派解决方案:
queryParams(): Map<String, String>
var pairs = location.search.replace("?", "").split("&")
var params = new Map<String, String>()
pairs.map(x =>
var pair = x.split("=")
if (pair.length == 2)
params.set(pair[0], pair[1])
)
return params
【讨论】:
【参考方案3】:查询和路径(Angular 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
字符串中,那么角度编码一个 URL 并且您得到类似 https://myapp.com/owner/123/show%3Fheight%323 的内容 - 上述解决方案将给出错误结果(queryParams 将为空,如果它在路径末端,则查询参数可以粘到最后一个路径参数)。在这种情况下改变导航方式to this
this.router.navigateByUrl(yourUrl);
【讨论】:
【参考方案4】:通过注入ActivatedRoute
的实例,可以订阅各种可观察对象,包括queryParams
和params
可观察对象:
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 非常正确地指出,根据官方文档,在这种情况下,组件onDestroy()
中的unsubscribe()
方法是不必要的。这已从我的代码示例中删除。 (见this教程中的蓝色警告框)
【讨论】:
我进一步建议用承诺替换订阅 - 在这种特殊情况下。 this.activatedRoute.params.toPromise() .then(response => ...) .catch(error => ...); 在哪里可以通过“activatedRoute”? 来自官方文档:我需要退订吗?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.
@Sobhan,是的,有区别。 switchMap 操作符返回一个 Observable,而 subscribe 操作符允许观察者(我们的组件)看到最终由 Observable 发出的项目。因此,在文档中有 2 个使用 switchmap 的实例。 1) 他们使用 switchMap 来附加对英雄的请求。 SwitchMap 与 subscribe 不同,它将确保在用户重新导航到路线的同时仍检索英雄时取消请求。 2) 使用异步管道。异步管道消耗一个可观察对象,因此不得订阅(异步管道会为您执行此操作)。
@richbray89 进一步指定“注意:根据您的要求,下面的 'queryParams' 可以替换为 'params'”:您在路由器中明确指定的部分,例如/user/:userId
在参数和“问号后面的东西”中,例如/user-search?name=albert
在查询参数中。【参考方案5】:
您只需在构造函数中注入 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() 仅在经过特定时间跨度且没有其他源发射的情况下从可观察的源发射一个值
【讨论】:
【参考方案6】:我希望它会帮助别人。
上面的问题指出,页面重定向后需要查询参数值,我们可以假设快照值(不可观察的替代方案)就足够了。
这里没有人提到来自official documentation 的snapshot.paramMap.get。
this.route.snapshot.paramMap.get('id')
所以在发送之前在发送/重定向组件中添加这个:
import Router from '@angular/router';
然后重定向为任一(记录在here):
this.router.navigate(['/heroes', id: heroId, foo: 'foo' ]);
或者简单地说:
this.router.navigate(['/heroes', heroId ]);
确保您已按照 here 的文档将其添加到路由模块中:
path: 'hero/:id', component: HeroDetailComponent
最后,在需要使用查询参数的组件中
添加导入(记录在here):
import Router, ActivatedRoute, ParamMap from '@angular/router';
注入ActivatedRoute
(文档还导入了 switchMap 并注入了 Router 和 HeroService - 但它们仅用于可观察的替代方案 - 当您使用快照替代方案时不需要它们,例如我们的案例):
constructor(
private route: ActivatedRoute
)
并获得您需要的价值(记录在案的here):
ngOnInit()
const id = this.route.snapshot.paramMap.get('id');
注意:如果您将路由模块添加到功能模块(如文档中所示),请确保在 APP.MODULE.ts 中路由模块出现在 AppRoutingModule(或具有根级应用程序路由的其他文件)之前: [] 。否则将找不到功能路线(因为它们会出现在 path: '**', redirectTo: '/not-found' 之后,您只会看到 not-found 消息)。
【讨论】:
【参考方案7】:现在是:
this.activatedRoute.queryParams.subscribe((params: Params) =>
console.log(params);
);
【讨论】:
感谢您提供此代码 sn-p,它可能会提供一些有限的短期帮助。一个正确的解释would greatly improve 它的长期价值,通过展示为什么这是一个很好的解决问题的方法,并且会使其对未来有其他类似问题的读者更有用。请编辑您的答案以添加一些解释,包括您所做的假设【参考方案8】:发送查询参数
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'];
);
Official source
【讨论】:
阅读效果很好。但它区分大小写。我们如何使它不区分大小写?【参考方案9】:如果你只想获取一次查询参数,最好的方法是使用take方法,这样你就不用担心退订了。 这是简单的sn-p:-
constructor(private route: ActivatedRoute)
route.snapshot.queryParamMap.take(1).subscribe(params =>
let category = params.get('category')
console.log(category);
)
注意:如果您以后想使用参数值,请删除 take(1)。
【讨论】:
【参考方案10】:我真的很喜欢@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
【讨论】:
当然需要注意的是,它将是初始值,不会反映后续更改。因此,如果您以编程方式更改 URL 参数作为逻辑的一部分,则需要注意 不确定这是否会随着更高版本的 Angular 发生变化,但我现在在 this.activatedRoute.snapshot.queryParams 中看到了它 对我来说this.activatedRoute.snapshot.queryParams
工作!【参考方案11】:
获取 URL 参数作为对象。
import Router from '@angular/router';
constructor(private router: Router)
console.log(router.parseUrl(router.url));
【讨论】:
【参考方案12】:您好,您可以使用 URLSearchParams,您可以阅读更多关于它的信息here。
导入:
import URLSearchParams from "@angular/http";
和功能:
getParam()
let params = new URLSearchParams(window.location.search);
let someParam = params.get('someParam');
return someParam;
注意:并非所有平台都支持,角度文档似乎处于“实验”状态
【讨论】:
这对我不起作用。我发现 window.location.search 包含查询字符串参数的前导问号。因此,第一个参数的键将带有问号。 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 来实现。【参考方案13】:
您可以使用ActivatedRoute在URL中传递查询参数,如下所述:-
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']));
【讨论】:
【参考方案14】:如果路由中未定义参数,则无法从 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);
【讨论】:
【参考方案15】:即使该问题指定版本 beta 7,该问题也出现在 Google 上的热门搜索结果中,用于搜索 angular 2 query parameters 等常用短语。出于这个原因,这里是最新路由器的答案(目前在 alpha.7 中)。
读取参数的方式发生了巨大变化。首先,您需要在构造函数参数中注入名为 Router
的依赖项,例如:
constructor(private router: Router)
然后我们可以在 ngOnInit
方法上订阅查询参数(构造函数也可以,但 ngOnInit
应该用于可测试性)
this.router
.routerState
.queryParams
.subscribe(params =>
this.selectedId = +params['id'];
);
在这个例子中,我们从像example.com?id=41
这样的URL读取查询参数id。
还有一些需要注意的地方:
-
像
params['id']
一样访问params
的属性总是返回一个字符串,并且可以通过在其前面加上+
前缀将其转换为数字。
使用 observable 获取查询参数的原因是它允许重复使用相同的组件实例而不是加载新的实例。每次更改查询参数时,都会引发我们订阅的新事件,因此我们可以对更改做出相应的反应。
【讨论】:
有没有办法让多个参数传给同一个成员?例如,我希望 'id' 或 'identification' 转到 this.selectedId。 @phandinhlan:嗯,这不是一个与 Angular 2 相关的问题。它当然可以实现,但你需要自己定义逻辑。基本上,您要做的是首先检查第一个键是否已定义,然后从中读取值,如果没有,则使用另一个键读取值。这可以通过if (params.hasOwnProperty('id')) this.selectedId = params['id'] else this.selectedId = params['identification']
之类的方式来实现。
是的,我最终做了类似的事情。我只是认为会有一些“内置”方式,例如: this.selectedId = +params['id']; this.selectedId = +params['identification'];当然这没有任何意义,也不起作用。【参考方案16】:
首先,我发现使用 Angular2 的结果是带有查询字符串的 url 将是 /path;query=value1
在您使用的组件中访问它 也是这样,但现在跟随一个代码块:
constructor(params: RouteParams)
var val = params.get("query");
至于为什么在加载组件时它会被删除,这不是默认行为。我专门检查了一个干净的测试项目,没有重定向或更改。它是默认路由还是路由的其他特殊之处?
在 https://angular.io/docs/ts/latest/guide/router.html#!#query-parameters 的 Angular2 教程中了解使用查询字符串和参数进行路由
【讨论】:
我不能使用像“;param1=value1;param2=value2”这样的参数,这个链接在另一个网站上生成并在我的网站上重定向,比如“example.com/auth?code_for_auth=askjfbkajdsbfksajdf” 目前在Angular2中设置路由的方式,我觉得不太可能。由于子路由确实依赖于矩阵 url,因此需要某种解决方法。至少据我所知。我会在我的网络服务器上拦截它并将它们转换为黑客,这很糟糕,但我现在想不出另一种方式 你不可能要求链接网站改变他们的网址? 没有。但是我解决了这个问题简单地手动解析Location.path() 此解决方案已弃用!以上是关于如何从 Angular 2 中的 url 获取查询参数?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Angular 的 HTTP 发布请求中传递 url 中的查询参数
如何从 getInitialProps 中的 url 获取查询参数?
如何从 Swift 3 xcode8 的 UIWebView 中的 url 获取查询字符串参数?