Cách quay lại trang cuối


367

Có cách nào thông minh để quay lại trang cuối trong Angular 2 không?

Cái gì đó như

this._router.navigate(LASTPAGE);

Ví dụ: trang C có một Go Backnút,

  • Trang A -> Trang C, nhấp vào nó, quay lại trang A.

  • Trang B -> Trang C, nhấp vào nó, quay lại trang B.

Liệu bộ định tuyến có thông tin lịch sử này?

Câu trả lời:


670

Trên thực tế, bạn có thể tận dụng dịch vụ Vị trí tích hợp, sở hữu API "Quay lại".

Tại đây (trong TypeScript):

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

@Component({
  // component's declarations here
})
class SomeComponent {

  constructor(private _location: Location) 
  {}

  backClicked() {
    this._location.back();
  }
}

Chỉnh sửa : Như được đề cập bởi @ charith.arumapperuma Locationnên được nhập từ @angular/commonđó vì vậy import {Location} from '@angular/common';dòng này rất quan trọng.


75
Vị trí phải được nhập từ "angular2 / bộ định tuyến" trong các bản phát hành cũ hơn của Angular 2. Trong các bản phát hành mới hơn, nó phải từ "@ angular / common".
charith.arumapperuma

2
Nếu bạn có nó được xây dựng trong khung, tôi không thấy bất kỳ lý do nào để sử dụng "bản gốc" "window.history.back ();" đó là một tính năng HTML5 ( developer.mozilla.org/en-US/docs/Web/API/Window/history )
Amir Sasson

7
Để biết giá trị của nó, tài liệu API Angular2 chính thức cho Locationcác trạng thái: "Lưu ý: tốt hơn là sử dụng dịch vụ Bộ định tuyến để kích hoạt thay đổi tuyến đường. Chỉ sử dụng Vị trí nếu bạn cần tương tác hoặc tạo URL bình thường bên ngoài định tuyến." Câu trả lời của @ Sasxa rõ ràng cho thấy một cách sử dụng Routerđể làm điều này. Tuy nhiên, Locationphương pháp chắc chắn là thuận tiện hơn. Có ai biết tại sao Routerphương pháp có thể đúng hơn Locationphương pháp không?
Andrew Willems

2
@Andrew: Tôi đã gặp phải sự cố, rằng bạn không thể quay lại hai lần, nếu bạn sử dụng this.location.back (). Bạn sẽ nhảy trở lại trang web ban đầu.
Johannes

1
@ yt61, không chắc chắn, có thể tái sử dụng? hoặc nếu bạn có thể đến một trang được chỉ định từ các tuyến khác nhau, vì vậy bạn không biết trước tuyến đường để quay lại.
Amir Sasson

111

Trong phiên bản cuối cùng của Angular 2.x / 4.x - đây là tài liệu https://angular.io/api/common/Location

/* typescript */

import { Location } from '@angular/common';
// import stuff here

@Component({
// declare component here
})
export class MyComponent {

  // inject location into component constructor
  constructor(private location: Location) { }

  cancel() {
    this.location.back(); // <-- go back to previous location on cancel
  }
}

1
Trong khi điều hướng trở lại màn hình trước, chúng ta có thể giữ lại các giá trị đã nhập mà không cần sử dụng một đối tượng trong dịch vụ.
Vignesh

Làm cách nào để hiển thị lại hình ảnh động trong khi location.back () đang thực thi?
Căn cứ tuyết

48

<button backButton>BACK</button>

Bạn có thể đặt điều này vào một lệnh, có thể được đính kèm với bất kỳ yếu tố có thể nhấp nào:

import { Directive, HostListener } from '@angular/core';
import { Location } from '@angular/common';

@Directive({
    selector: '[backButton]'
})
export class BackButtonDirective {
    constructor(private location: Location) { }

    @HostListener('click')
    onClick() {
        this.location.back();
    }
}

Sử dụng:

<button backButton>BACK</button>

thật tuyệt vời
Rafael de Castro

1
Nếu bạn làm mới trên trang này và nhấp vào nút kích hoạt "this.location.back ()", nó sẽ chỉ kích hoạt làm mới trang. Có cách nào mà mô-đun Location có thể phát hiện nếu đường dẫn trước đó tồn tại không?
Henry LowCZ

người đàn ông làm việc tốt ;)
elciospy

Hãy ghi nhớ nếu người dùng truy cập trực tiếp vào trang có nút Quay lại và nếu anh ta nhấp vào nút .. thì anh ta sẽ bị ném khỏi ứng dụng đến trang trước theo lịch sử trình duyệt (nền tảng).
hastrb

Đối với độc giả tương lai, nhìn vào tài liệu API
hastrb

23

Đã thử nghiệm với Angular 5.2.9

Nếu bạn sử dụng một neo thay vì một nút, bạn phải làm cho nó một liên kết thụ động với href="javascript:void(0)"để làm cho công việc Location góc.

app.component.ts

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

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent {

  constructor( private location: Location ) { 
  }

  goBack() {
    // window.history.back();
    this.location.back();

    console.log( 'goBack()...' );
  }
}

app.component.html

<!-- anchor must be a passive link -->
<a href="javascript:void(0)" (click)="goBack()">
  <-Back
</a>

Tôi sẽ đề nghị tạo một lệnh 'clickPreventDefault' thay vì sử dụng javascript:void(0). Một cái gì đó như ... @Directive({ selector: '[clickPreventDefault]' }) export class ClickPreventDefaultDirective { @HostListener("click", ["$event"]) onClick($event: Event) { $event.preventDefault(); } }
bmd

Cảm ơn bạn @bmd, đó là một cách phức tạp hơn nhưng nó cũng hoạt động. Một giải pháp làm việc khác là không sử dụng herf: <a (click)="goBack()"> mặc dù cách này không vượt qua Trình xác thực HTML.
JavierFuentes

20

Bạn có thể thực hiện routerOnActivate()phương thức trên lớp tuyến đường của bạn, nó sẽ cung cấp thông tin về tuyến đường trước đó.

routerOnActivate(nextInstruction: ComponentInstruction, prevInstruction: ComponentInstruction) : any

Sau đó, bạn có thể sử dụng router.navigateByUrl()và truyền dữ liệu được tạo từ ComponentInstruction. Ví dụ:

this._router.navigateByUrl(prevInstruction.urlPath);

Điều này vẫn còn hiệu lực cho Angular 2.1.0?
smartmouse

1
@smartmouse Tôi không nghĩ vậy, có tài liệu chorouterOnActivate
Bojan Kogoj

4
Liên kết routerOnActivate () trong câu trả lời này bị hỏng. Có vẻ như đây không phải là cách để làm điều đó trong phiên bản phát hành.
rmcsharry

14

Cũng làm việc cho tôi khi tôi cần di chuyển trở lại như trong hệ thống tập tin. PS @angular: "^ 5.0.0"

<button type="button" class="btn btn-primary" routerLink="../">Back</button>

7
Tôi đã hy vọng điều này sẽ hoạt động, nhưng điều này quay trở lại Tuyến đường tiếp theo phía trên nó - không phải là tuyến đường bạn đã đi trước khi điều hướng đến trang. Thật tốt khi biết điều này tồn tại, nhưng nếu bạn có nhiều điểm nhập cảnh cho thành phần của mình, phương thức này sẽ chỉ quay trở lại tuyến đường phía trên nó, chứ không phải nơi bạn bắt nguồn.
Scott Byers

Khi tôi viết "khi tôi cần quay lại như trong hệ thống tập tin" :) Đối với tôi, hành vi này cũng thật bất ngờ.
Shevtsiv Andriy

12

Tôi đã tạo một nút tôi có thể sử dụng lại bất cứ nơi nào trên ứng dụng của mình.

Tạo thành phần này

import { Location } from '@angular/common';
import { Component, Input } from '@angular/core';

@Component({
    selector: 'back-button',
    template: `<button mat-button (click)="goBack()" [color]="color">Back</button>`,
})
export class BackButtonComponent {
    @Input()color: string;

  constructor(private location: Location) { }

  goBack() {
    this.location.back();
  }
}

Sau đó thêm nó vào bất kỳ mẫu nào khi bạn cần một nút quay lại.

<back-button color="primary"></back-button>

Lưu ý: Đây là sử dụng Tài liệu góc, nếu bạn không sử dụng thư viện đó thì hãy xóa mat-buttoncolor.


Liệu cách tiếp cận này làm việc với các cửa hàng bộ định tuyến được đặt tên mặc dù? Nói rằng tôi có một số trên trang và chỉ muốn quay lại một trong số họ, điều này có hoạt động không?
RRD

Bạn sẽ phải sử dụng một cách tiếp cận khác cho tình huống đó. Nếu bạn có cùng một nút quay lại ở hai ổ cắm bộ định tuyến khác nhau, có thể cả hai sẽ làm điều tương tự và quay lại ổ cắm bộ định tuyến cuối cùng đã được thay đổi.
Todd Skelton

Đối với các cửa hàng được đặt tên, tôi thấy rằng cách tiếp cận này có hiệu quả: this.router.navigate (['../'], {RelTo: this.route})
rrd

Làm thế nào để sử dụng thành phần này bên trong một thành phần khác?
RN Kushwaha

12

Sau tất cả những câu trả lời tuyệt vời này, tôi hy vọng câu trả lời của tôi tìm thấy ai đó và giúp đỡ họ. Tôi đã viết một dịch vụ nhỏ để theo dõi lịch sử tuyến đường. Nó đi từ đây.

import { Injectable } from '@angular/core';
import { NavigationEnd, Router } from '@angular/router';
import { filter } from 'rxjs/operators';

@Injectable()
export class RouteInterceptorService {
  private _previousUrl: string;
  private _currentUrl: string;
  private _routeHistory: string[];

  constructor(router: Router) {
    this._routeHistory = [];
    router.events
      .pipe(filter(event => event instanceof NavigationEnd))
      .subscribe((event: NavigationEnd) => {
        this._setURLs(event);
      });
  }

  private _setURLs(event: NavigationEnd): void {
    const tempUrl = this._currentUrl;
    this._previousUrl = tempUrl;
    this._currentUrl = event.urlAfterRedirects;
    this._routeHistory.push(event.urlAfterRedirects);
  }

  get previousUrl(): string {
    return this._previousUrl;
  }

  get currentUrl(): string {
    return this._currentUrl;
  }

  get routeHistory(): string[] {
    return this._routeHistory;
  }
}

Sau khi thử ít nhiều tất cả các giải pháp, tôi thấy cách này là cách phù hợp hơn để làm điều đó
A. D'Alfonso

Điều gì sẽ xảy ra nếu tôi mở trang trên liên kết cụ thể và tôi muốn nó sẽ quay trở lại trang trong cây trang?
Ivan

8

Cách tôi đã làm trong khi điều hướng đến trang khác, thêm tham số truy vấn bằng cách chuyển vị trí hiện tại

this.router.navigate(["user/edit"], { queryParams: { returnUrl: this.router.url }

Đọc thông số truy vấn này trong thành phần của bạn

this.router.queryParams.subscribe((params) => {
    this.returnUrl = params.returnUrl;
});

Nếu returnUrl có mặt, bật nút quay lại và khi người dùng nhấp vào nút quay lại

this.router.navigateByUrl(this.returnUrl); // Hint taken from Sasxa

Điều này sẽ có thể điều hướng đến trang trước. Thay vì sử dụng location.back Tôi cảm thấy phương pháp trên an toàn hơn, hãy xem xét trường hợp người dùng trực tiếp đến trang của bạn và nếu anh ta nhấn nút quay lại với location.back, nó sẽ chuyển hướng người dùng đến trang trước đó sẽ không phải là trang web của bạn.


Cần nhập ActivatedRoute và sử dụng thay vì Bộ định tuyến trên đăng ký queryParams (ví dụ: this.route.queryParams.subscribe), nhưng nếu không, dường như hoạt động!
Stephen Kaiser

đối với tôi nó hoạt động tốt với chính bộ định tuyến ngay cả trong góc 4
Puneeth Rai

1
Câu trả lời hay nhất, nhưng trong Angular 5 (tối đa x?), Bạn cần tiêm một đối tượng "ActivatedRoute" và sử dụng queryParams trên đối tượng này, như Stephen Kaiser đã nêu.
Satria


3

Để quay lại mà không làm mới trang, Chúng tôi có thể làm bằng html như bên dưới javascript: history.back ()

<a class="btn btn-danger" href="javascript:history.back()">Go Back</a>

Tôi sẽ khuyên bạn nên sử dụng Locationdịch vụ thay thế. API chính thức
hastrb

2

Kể từ phiên bản beta 18:

import {Location} from 'angular2/platform/common';



2

Giải pháp khác

window.history.back();


Hoạt động cho tôi location.back () cũng hoạt động nhưng tôi không biên dịch với --prod
Alex
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.