更改路线参数而无需在Angular 2中重新加载


112

我正在使用Angular 2,Google Maps等创建房地产网站,并且当用户更改地图中心时,我对API进行搜索,以指示地图的当前位置以及半径。问题是,我想在不重新加载整个页面的情况下将这些值反映在url中。那可能吗?我已经找到了一些使用AngularJS 1.x的解决方案,但是关于Angular 2却一无所获。


我认为,如果您使用[routerLink] =“ ['/ route',{param1:value1}],它将不会重新加载页面
Toolkit

但是如何添加另一个查询参数?
工具包

2
☝️它将导致页面重新加载
LifterCoder

请注意,如果您使用SSR来使您的站点SEO兼容,那么这是一个有争议的问题。
乔纳森(Jonathan)

@乔纳森,是吗?由于一旦渲染了静态页面,Angular就会接管路由,所以即使使用SSR,我也认为这仍然是一个有效的问题。
adam0101

Answers:


90

您可以使用location.go(url)它将基本上更改您的网址,而无需更改应用程序的路径。

注意这可能会导致其他影响,例如从当前路由重定向到子路由。

描述的相关问题location.go不会牵扯Router到发生变化。


2
我的路线有一个名为“搜索”的参数,其中接收到搜索字段的序列化版本,当列表状态首次加载时,我只使用this._routeParams.get('search')读取这些参数,反序列化过滤器并执行搜索。如果用户通过使用地图或搜索构面来更改搜索字段,我只是使用路由器的var指令= this._router.generate(['Listing',{search:serializedFields}]的生成方法来构造正确的url。 ),然后使用this._location.go(instruction.urlPath)更改网址,而无需重新加载状态。
Marcos Basualdo

20
如果有人想知道:从“ angular2 / platform / common”导入{Location};
Kesarion '16

18
import { Location } from '@angular/common';在Angular 4中
tehCivilian

2
你decared constructr喜欢constructor(private location: Location){ }
潘卡Parkar

2
@AdrianE问题很可能是location.go()您应该键入时输入的this.location.go()。发出时this.,您将调用Typescript的location-interface。
georg-un

94

从RC6开始,您可以执行以下操作以更改URL而不更改状态,从而保留您的路由历史记录

import {OnInit} from '@angular/core';

import {Location} from '@angular/common'; 
// If you dont import this angular will import the wrong "Location"

@Component({
  selector: 'example-component',
  templateUrl: 'xxx.html'
})
export class ExampleComponent implements OnInit
{
  constructor( private location: Location )
  {}

  ngOnInit()
  {    
    this.location.replaceState("/some/newstate/");
  }
}

这对我不起作用。它会尝试加载路线。控制台错误:Error: Uncaught (in promise): Error: Cannot match any routes. URL Segment: 'some/newstate'
Inigo

2
将其与@golfadas建议的url创建结合起来,我们就有一个赢家!
crowmagnumb

63

使用location.go(url)方法是可行的,但不要硬编码url,而应考虑使用生成它router.createUrlTree()

假设您要执行以下路由器调用:this.router.navigate([{param: 1}], {relativeTo: this.activatedRoute})但无需重新加载组件,则可以将其重写为:

const url = this.router.createUrlTree([], {relativeTo: this.activatedRoute, queryParams: {param: 1}}).toString()

 this.location.go(url);

9
这个答案解决了我的问题。一个问题,上面生成的url具有以“;”(分号)分隔的参数。为了用“&”分隔查询中的每个参数,我们应该怎么做?
Amarnath

2
这是createUrlTree的声明(命令:any [],navigationExtras?:NavigationExtras)。您必须使用位于navigationExtras上的queryParams而不是逗号。createUrlTree([],{relativeTo:this.activatedRoute,queryParams:{param:1}})
套件

只是要弄清楚@kit的意思,请执行以下操作:this.router.createUrlTree([], {relativeTo: this.activatedRoute, queryParams: {param: 1}}).toString()
bluegrounds

12

对于像我这样的人来说,找到以下问题可能是有用的。

我遇到了类似的问题,最初尝试按照此处其他答案中的建议使用location.go和location.replaceState。但是,当我不得不导航到应用程序上的另一个页面时,我遇到了问题,因为导航是相对于当前路线的,并且当前路线没有被location.go或location.replaceState更新(路由器不知道任何内容)关于这些对网址的作用)

本质上,我需要一个解决方案,当路由参数更改但DID在内部更新路由状态时,DIDN不会重新加载页面/组件。

我最终使用了查询参数。您可以在这里找到有关它的更多信息:https : //angular-2-training-book.rangle.io/handout/routing/query_params.html

因此,如果您需要执行诸如保存订单和获取订单ID之类的操作,则可以如下所示更新页面URL。更新中心位置和地图上的相关数据将类似

// let's say we're saving an order. Initally the URL is just blah/orders
save(orderId) {
    // [Here we would call back-end to save the order in the database]

    this.router.navigate(['orders'], { queryParams: { id: orderId } });
    // now the URL is blah/orders?id:1234. We don't reload the orders
    // page or component so get desired behaviour of not seeing any 
    // flickers or resetting the page.
}

然后在ngOnInit方法中跟踪它,例如:

ngOnInit() {
    this.orderId = this.route
        .queryParamMap
        .map(params => params.get('id') || null);
    // orderID is up-to-date with what is saved in database now, or if
    // nothing is saved and hence no id query paramter the orderId variable
    // is simply null.
    // [You can load the order here from its ID if this suits your design]
}

如果您需要使用新的(未保存的)订单直接进入订单页面,可以执行以下操作:

this.router.navigate(['orders']);

或者,如果您需要直接转到现有(已保存)订单的订单页面,则可以执行以下操作:

this.router.navigate(['orders'], { queryParams: { id: '1234' } });

10

我很难让它在angular2的RCx版本中工作。Location包已移动,构造函数()中的location.go()运行无法正常工作。在生命周期中,它必须为ngOnInit()或更高版本。这是一些示例代码:

import {OnInit} from '@angular/core';
import {Location} from '@angular/common';

@Component({
  selector: 'example-component',
  templateUrl: 'xxx.html'
})
export class ExampleComponent implements OnInit
{
  constructor( private location: Location )
  {}

  ngOnInit()
  {    
    this.location.go( '/example;example_param=917' );
  }
}

以下是有关此问题的有角度的资源:https : //angular.io/docs/ts/latest/api/common/index/Location-class.html https://angular.io/docs/ts/latest/api/ common / index / LocationStrategy-class.html


7

我用这种方式得到它:

const queryParamsObj = {foo: 1, bar: 2, andThis: 'text'};

this.location.replaceState(
  this.router.createUrlTree(
    [this.locationStrategy.path().split('?')[0]], // Get uri
    {queryParams: queryParamsObj} // Pass all parameters inside queryParamsObj
  ).toString()
);

-编辑-

我认为我应该为此添加更多信息。

如果您使用的this.location.replaceState()路由器的应用程序未更新,那么以后使用路由器的信息在浏览器中并不相同。例如,如果您localizeService曾经使用过更改语言,则在将语言切换后,您的应用程序将返回到您使用进行更改之前的最后一个URL this.location.replaceState()

如果您不希望出现这种情况,则可以选择其他更新URL的方法,例如:

this.router.navigate(
  [this.locationStrategy.path().split('?')[0]],
  {queryParams: queryParamsObj}
);

在此选项中,您的浏览器也不会刷新,但是您所做的URL更改也会注入到Router您的应用程序中,因此,在切换语言时,您不会遇到in中的问题this.location.replaceState()

当然,您可以根据需要选择方法。首先,它更轻便,因为您使用应用程序所需要的不仅仅是URL浏览器的更改。


3

对我来说,实际上是Angular 4.4.5的结合。

使用router.navigate通过不遵守realtiveTo:ActivateRoute部分来不断破坏我的网址。

我最终得到了:

this._location.go(this._router.createUrlTree([this._router.url], { queryParams: { profile: value.id } }).toString())

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.