Angular:如何在不更改路线的情况下更新 queryParams
Posted
技术标签:
【中文标题】Angular:如何在不更改路线的情况下更新 queryParams【英文标题】:Angular: How to update queryParams without changing route 【发布时间】:2017-09-27 14:59:31 【问题描述】:我正在尝试从组件中更新(添加、删除)queryParams。在 angularJS 中,它曾经是可能的,这要归功于:
$location.search('f', 'filters[]'); // setter
$location.search()['filters[]']; // getter
我有一个应用程序,其中包含用户可以过滤、订购等的列表,我想在 url 的 queryParams 中设置所有激活的过滤器,以便他可以复制/粘贴 url 或与其他人共享。
但是,我不希望每次选择过滤器时都重新加载我的页面。
新路由器可以做到这一点吗?
【问题讨论】:
【参考方案1】:您可以使用新的查询参数导航到当前路线,这不会重新加载您的页面,但会更新查询参数。
类似的东西(在组件中):
constructor(private router: Router)
public myMethodChangingQueryParams()
const queryParams: Params = myParam: 'myNewValue' ;
this.router.navigate(
[],
relativeTo: activatedRoute,
queryParams: queryParams,
queryParamsHandling: 'merge', // remove to replace all query params by provided
);
请注意,虽然它不会重新加载页面,但它会将新条目推送到浏览器的历史记录中。如果您想在历史记录中替换它而不是在那里添加新值,您可以使用 queryParams: queryParams, replaceUrl: true
。
编辑:
正如 cmets 中已经指出的那样,[]
和 relativeTo
属性在我的原始示例中丢失了,因此它也可能更改了路由,而不仅仅是查询参数。在这种情况下,正确的 this.router.navigate
用法将是:
this.router.navigate(
[],
relativeTo: this.activatedRoute,
queryParams: myParam: 'myNewValue' ,
queryParamsHandling: 'merge'
);
将新参数值设置为 null
将从 URL 中删除参数。
【讨论】:
我必须使用[]
而不是 ['.']
才能使其工作
需要使用queryParams['relativeTo'] = this.activatedRoute;使导航相对于当前页面
解决 OP 问题的好方法。除非我遗漏了什么,否则它无法让您在当前页面的历史记录中前后移动(例如,更改过滤器或订购 5 次,每个都有自己的 URL 但相同的组件)并拥有如果您直接访问这 5 个 URL,页面的内容会如何显示。我认为您可以通过this.activatedRoute.queryParams.subscribe
手动完成此操作并在您的组件中进行各种更新,但是是否有一种简单的 Angular 方法来加载路由,以便自动前后工作?
这实际上会破坏组件并在每次更改 url 参数时调用 ngOnit()。有没有办法避免调用 ngOnit() ?
在使用 router.navigate 时,它会滚动窗口顶部,有什么办法可以禁用它吗?【参考方案2】:
@Radosław Roszkowiak 的答案几乎是正确的,除了relativeTo: this.route
是必需的,如下所示:
constructor(
private router: Router,
private route: ActivatedRoute,
)
changeQuery()
this.router.navigate(['.'], relativeTo: this.route, queryParams: ... );
【讨论】:
【参考方案3】:在 Angular 5 中,您可以通过解析当前 url 轻松获取和修改 urlTree 的副本。这将包括查询参数和片段。
let urlTree = this.router.parseUrl(this.router.url);
urlTree.queryParams['newParamKey'] = 'newValue';
this.router.navigateByUrl(urlTree);
修改查询参数的“正确方法”可能是 createUrlTree 如下所示,它从当前创建一个新的 UrlTree,同时让我们使用 NavigationExtras 对其进行修改。
import Router from '@angular/router';
constructor(private router: Router)
appendAQueryParam()
const urlTree = this.router.createUrlTree([],
queryParams: newParamKey: 'newValue' ,
queryParamsHandling: "merge",
preserveFragment: true );
this.router.navigateByUrl(urlTree);
要以这种方式删除查询参数,您可以将其设置为undefined
或null
。
【讨论】:
navigateByUrl
与 navigate
不同——不仅仅是 UrlTree 参数。见***.com/a/45025432/271012【参考方案4】:
投票最多的答案部分对我有用。浏览器 url 保持不变,但我的 routerLinkActive
在导航后不再工作。
我的解决方案是使用 lotation.go:
import Component from "@angular/core";
import Location from "@angular/common";
import HttpParams from "@angular/common/http";
export class whateverComponent
constructor(private readonly location: Location, private readonly router: Router)
addQueryString()
const params = new HttpParams();
params.append("param1", "value1");
params.append("param2", "value2");
this.location.go(this.router.url.split("?")[0], params.toString());
我使用 HttpParams 来构建查询字符串,因为我已经使用它通过 httpClient 发送信息。但你可以自己构建它。
和this._router.url.split("?")[0]
,是从当前url中删除所有以前的查询字符串。
【讨论】:
这应该是公认的答案,router.navigates 也会刷新 ngOnit,location.go 不会这样做!这非常重要,因为如果您的组件执行一些 ngOnit 逻辑(HTTP 调用等),它们将在您使用 router.navigate 时再次被调用。你不想要这个。 为什么需要路由器,只用于 url?this.location.path().split...
不是更好吗?
@Vladimir 你可能是对的,我在我的组件中将它用于其他目的,所以不仅仅是为了那个。不过我没时间验证。
如果您想保留查询参数,例如促销或谷歌跟踪参数,这将不起作用
这是唯一对我有用的答案,而且实际上是有道理的。【参考方案5】:
试试
this.router.navigate([],
queryParams:
query: value
);
将适用于除单引号之外的相同路线导航。
【讨论】:
【参考方案6】:如果您想更改查询参数而不更改路由。见下文
示例可能会帮助您:
当前路线是:/search
& 目标路线是(没有重新加载页面):/search?query=love
submit(value: string)
this.router.navigate( ['.'], queryParams: query: value )
.then(_ => this.search(q));
search(keyword:any)
//do some activity using
请注意:您可以使用this.router.navigate( ['search']
代替this.router.navigate( ['.']
【讨论】:
我不确定 [.] 是不是比relativeTo:
更好的方法,但 .then()
很有帮助 - 不知道 navigate() 返回了一个承诺,很高兴你发布了!
不用['.']或['search'],我们可以简单地使用[]【参考方案7】:
我最终将urlTree
与location.go
结合在一起
const urlTree = this.router.createUrlTree([],
relativeTo: this.route,
queryParams:
newParam: myNewParam,
,
queryParamsHandling: 'merge',
);
this.location.go(urlTree.toString());
不确定toString
是否会导致问题,但不幸的是location.go
似乎是基于字符串的。
【讨论】:
这不会触发对queryParamMap observable的观察者的更新【参考方案8】:更好 - 只是 html:
<a [routerLink]="[]" [queryParams]="key: 'value'">Your Query Params Link</a>
注意空数组,而不是只做routerLink=""
或[routerLink]="''"
【讨论】:
为什么是空数组? [routerLink]="" 有效。【参考方案9】:首先,我们需要从 Angular 路由器中导入路由器模块并声明其别名
import Router from '@angular/router'; ---> import
class AbcComponent implements OnInit()
constructor(
private router: Router ---> decalre alias name
)
1。您可以使用“router.navigate”函数更改查询参数并传递查询参数
this.router.navigate([], queryParams: _id: "abc", day: "1", name: "dfd"
);
它将更新当前即激活路由中的查询参数
下面将重定向到带有_id,day的abc页面 并命名为查询参数
this.router.navigate(['/abc'], queryParams: _id: "abc", day: "1", name: “dfd” );
它将更新“abc”路由中的查询参数以及三个查询参数
获取查询参数:-
import ActivatedRoute from '@angular/router'; //import activated routed
export class ABC implements OnInit
constructor(
private route: ActivatedRoute //declare its alias name
)
ngOnInit()
console.log(this.route.snapshot.queryParamMap.get('_id')); //this will fetch the query params
【讨论】:
【参考方案10】:Angular 的定位服务应该在与浏览器的 URL 交互时使用,而不是用于路由。这就是为什么我们要使用Location 服务。
Angulars HttpParams 用于创建查询参数。请记住 HttpParam 是不可变的,这意味着在创建值时必须将其链接起来。
最后,使用this._location.replaceState
更改为URL而不重新加载页面/路由和原生js location.path
获取不带参数的url每次重置参数。
constructor(
private _location: Location,
)
...
updateURLWithNewParamsWithoutReloading()
const params = new HttpParams().appendAll(
price: 100,
product: 'bag'
);
this._location.replaceState(
location.pathname,
params.toString()
);
【讨论】:
以上是关于Angular:如何在不更改路线的情况下更新 queryParams的主要内容,如果未能解决你的问题,请参考以下文章
如何在不订阅 Angular 表单提交的情况下创建/更新项目
如何在不更改后端的情况下解决 Angular 8 中的 CORS 问题?
在 angular2 的新页面中,路线更改视图不会滚动到顶部
如何在不重新加载页面的情况下从 FF Web 扩展内容脚本更改 3rd 方网站上的 Angular 应用程序路由/URL