Thay đổi thông số tuyến đường mà không cần tải lại trong Angular 2


114

Tôi đang tạo trang web bất động sản bằng cách sử dụng Angular 2, Google Maps, v.v. và khi người dùng thay đổi tâm bản đồ, tôi thực hiện tìm kiếm đối với API cho biết vị trí hiện tại của bản đồ cũng như bán kính. Vấn đề là, tôi muốn phản ánh những giá trị đó trong url mà không cần tải lại toàn bộ trang. Điều đó có thể không? Tôi đã tìm thấy một số giải pháp sử dụng AngularJS 1.x nhưng không có gì về Angular 2.


tôi nghĩ nếu bạn sử dụng [routerLink] = "['/ route', {param1: value1}] thì nó sẽ không tải lại trang
Bộ công cụ

nhưng làm cách nào để thêm một tham số truy vấn khác?
Bộ công cụ

2
☝️ nó sẽ gây ra tải lại trang
LifterCoder

Chỉ cần lưu ý rằng nếu bạn sử dụng SSR để làm cho trang web của bạn tương thích với SEO, thì đây là một vấn đề tranh cãi.
Jonathan

@Jonathan, phải không? Vì Angular tiếp quản việc định tuyến sau khi trang tĩnh được hiển thị, tôi nghĩ đó vẫn là một câu hỏi hợp lệ ngay cả khi sử dụng SSR.
adam0101

Câu trả lời:


92

Bạn có thể sử dụng location.go(url)điều này về cơ bản sẽ thay đổi url của bạn mà không cần thay đổi lộ trình ứng dụng.

LƯU Ý điều này có thể gây ra hiệu ứng khác như chuyển hướng đến tuyến con từ tuyến hiện tại.

Câu hỏi liên quan mà mô tảlocation.gosẽ không chính xácRouterđể xảy ra thay đổi.


2
Tuyến đường của tôi có một tham số có tên là 'tìm kiếm' trong đó nhận được phiên bản tuần tự hóa của các trường tìm kiếm, khi trạng thái danh sách tải lần đầu tiên, tôi chỉ đọc các tham số đó bằng this._routeParams.get ('search'), giải mã hóa các bộ lọc và thực hiện tìm kiếm. Nếu người dùng thay đổi các trường tìm kiếm, bằng cách sử dụng bản đồ hoặc các khía cạnh tìm kiếm, tôi chỉ cần tạo url chính xác bằng cách sử dụng phương thức tạo của bộ định tuyến var hướng dẫn = this._router.generate (['Listing', {search: serializedFields}] ) và sau đó sử dụng this._location.go (hướng dẫn.urlPath) để thay đổi url mà không cần tải lại trạng thái.
Marcos Basualdo

20
Nếu còn ai thắc mắc: hãy nhập {Location} từ 'angle2 / platform / common';
Kesarion

18
import { Location } from '@angular/common';ở góc 4
tehCivilian

2
Bạn có decared constructr nhưconstructor(private location: Location){ }
Pankaj Parkar

2
@AdrianE, vấn đề có lẽ là do bạn đã nhập location.go()trong khi đáng lẽ phải nhập this.location.go(). Khi bạn phát ra this., bạn gọi giao diện vị trí của Typecript.
georg-un

94

Kể từ RC6, bạn có thể làm như sau để thay đổi URL mà không thay đổi trạng thái và do đó giữ lịch sử tuyến đường của bạn

    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/");
        }
    }

Điều này không hiệu quả với tôi. Nó sẽ cố gắng tải tuyến đường. Lỗi bảng điều khiển:Error: Uncaught (in promise): Error: Cannot match any routes. URL Segment: 'some/newstate'
Inigo

2
Kết hợp điều này với tạo url theo đề xuất của @golfadas và chúng tôi có một người chiến thắng!
crowmagnumb

63

Sử dụng location.go(url)là cách để thực hiện, nhưng thay vì mã hóa cứng url, hãy cân nhắc tạo nó bằng cách sử dụng router.createUrlTree().

Giả sử bạn muốn thực hiện lệnh gọi bộ định tuyến sau: this.router.navigate([{param: 1}], {relativeTo: this.activatedRoute})nhưng không tải lại thành phần, nó có thể được viết lại thành:

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

 this.location.go(url);

9
Câu trả lời này đã giải quyết được vấn đề của tôi. Một câu hỏi, url được tạo ở trên có các tham số được phân cách bằng ";" (dấu chấm phẩy). Chúng ta nên làm gì để tách từng tham số trong truy vấn bằng "&"?
Amarnath

2
đây là khai báo của createUrlTree (các lệnh: any [], navigationExtras ?: NavigationExtras). bạn phải sử dụng queryParams định vị navigationExtras không phải dấu phẩy. createUrlTree ([], {relativeTo: this.actiisedRoute, queryParams: {param: 1}})
kit

chỉ để làm rõ những gì @kit đã nói, hãy làm điều này:this.router.createUrlTree([], {relativeTo: this.activatedRoute, queryParams: {param: 1}}).toString()
bluegrounds

12

Đối với bất kỳ ai như tôi tìm thấy câu hỏi này, những điều sau có thể hữu ích.

Tôi đã gặp sự cố tương tự và ban đầu đã thử sử dụng location.go và location.replaceState như được đề xuất trong các câu trả lời khác tại đây. Tuy nhiên, tôi đã gặp phải sự cố khi phải điều hướng đến một trang khác trên ứng dụng vì điều hướng liên quan đến tuyến đường hiện tại và tuyến đường hiện tại không được cập nhật bởi location.go hoặc location.replaceState (bộ định tuyến không biết gì cả về những gì chúng làm với URL)

Về bản chất, tôi cần một giải pháp KHÔNG tải lại trang / thành phần khi tham số tuyến thay đổi nhưng DID cập nhật trạng thái tuyến trong nội bộ.

Tôi đã kết thúc bằng cách sử dụng các tham số truy vấn. Bạn có thể tìm thêm về nó tại đây: https://angular-2-training-book.rangle.io/handout/routing/query_params.html

Vì vậy, nếu bạn cần làm điều gì đó như lưu đơn hàng và lấy ID đơn hàng, bạn có thể cập nhật URL trang của mình như hình dưới đây. Cập nhật vị trí trung tâm và dữ liệu liên quan trên bản đồ sẽ tương tự

// 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.
}

và bạn theo dõi nó trong phương thức ngOnInit như:

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]
}

Nếu bạn cần đi thẳng đến trang đặt hàng với một đơn hàng mới (chưa được lưu), bạn có thể thực hiện:

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

Hoặc nếu bạn cần truy cập trực tiếp vào trang đặt hàng cho một đơn hàng hiện có (đã lưu), bạn có thể thực hiện:

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

10

Tôi đã gặp khó khăn lớn khi làm cho điều này hoạt động trong các bản RCx của angle2. Gói Vị trí đã di chuyển và chạy location.go () bên trong constructor () sẽ không hoạt động. Nó cần phải là ngOnInit () hoặc mới hơn trong vòng đời. Đây là một số mã ví dụ:

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' );
  }
}

Dưới đây là các tài nguyên góc cạnh về vấn đề này: 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

Tôi sử dụng cách này để lấy nó:

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()
);

-- BIÊN TẬP --

Tôi nghĩ rằng tôi nên thêm một số thông tin cho điều này.

Nếu bạn sử dụng this.location.replaceState()bộ định tuyến của ứng dụng của bạn không được cập nhật, vì vậy nếu bạn sử dụng bộ định tuyến sau đó, thông tin này sẽ không bình đẳng trong trình duyệt của bạn. Ví dụ: nếu bạn sử dụng localizeServiceđể thay đổi ngôn ngữ, sau khi chuyển đổi ngôn ngữ, ứng dụng của bạn trở lại URL cuối cùng mà bạn đã ở trước đó this.location.replaceState().

Nếu bạn không muốn hành vi này, bạn có thể chọn phương pháp khác để cập nhật URL, như:

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

Trong tùy chọn này, trình duyệt của bạn cũng không làm mới nhưng URLthay đổi của bạn cũng được đưa vào Routerứng dụng của bạn, vì vậy khi bạn chuyển đổi ngôn ngữ, bạn không gặp vấn đề như trong this.location.replaceState().

Tất nhiên bạn có thể chọn phương pháp cho nhu cầu của bạn. Thứ nhất nhẹ hơn vì bạn không tham gia vào ứng dụng của mình nhiều hơn là thay đổi URLtrình duyệt.


3

Đối với tôi, nó thực sự là sự kết hợp của cả hai với Angular 4.4.5.

Sử dụng router.navigate tiếp tục phá hủy url của tôi bằng cách không tôn trọng phần realtiveTo: activeRoute.

Tôi đã kết thúc với:

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

3

Sử dụng thuộc tính queryParamsHandling: 'merge' trong khi thay đổi url.

this.router.navigate([], {
        queryParams: this.queryParams,
        queryParamsHandling: 'merge',
        replaceUrl: true,
});

3
Điều này khiến thành phần hiện được định tuyến được tải lại
btx
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.