Как вернуться на последнюю страницу

370

Есть ли умный способ вернуться на последнюю страницу в Angular 2?

Что-то вроде

this._router.navigate(LASTPAGE);

Например, на странице C есть Go Backкнопка,

  • Страница A -> Страница C, щелкните ее, чтобы вернуться на страницу A.

  • Страница B -> Страница C, щелкните ее, чтобы вернуться на страницу B.

Есть ли у роутера эта история?

Хунбо Мяо
источник

Ответы:

673

На самом деле вы можете воспользоваться встроенной службой определения местоположения, которая владеет API «Back».

Здесь (в 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();
  }
}

Редактировать : Как упоминается @ charith.arumapperuma Locationследует импортировать из, @angular/commonтак что import {Location} from '@angular/common';линия важна.

Амир Сассон
источник
75
Расположение должно быть импортировано из «angular2 / router» в более старых выпусках Angular 2. В более новых выпусках это должно быть из «@ angular / common».
charith.arumapperuma
2
Если он встроен в фреймворк, я не вижу никакой причины использовать "native" "window.history.back ();" которая является функцией HTML5 ( developer.mozilla.org/en-US/docs/Web/API/Window/history )
Амир Сассон,
7
Для чего стоит официальная документация по Angular2 API для Locationсостояний: «Примечание: лучше использовать сервис Router для запуска изменений маршрута. Используйте Location только в том случае, если вам нужно взаимодействовать или создавать нормализованные URL-адреса вне маршрутизации». Ответ Сассы, по- видимому, показывает, как это Routerсделать. Однако Locationметод определенно более удобен. Кто-нибудь знает, почему Routerметод может быть более правильным, чем Locationметод?
Эндрю Виллемс
2
@ Андрей: я столкнулся с проблемой, что вы не можете вернуться назад два раза, если вы используете this.location.back (). Вы вернетесь на исходный сайт.
Йоханнес
1
@ yt61, не уверен, возможно повторное использование? или если вы можете попасть на указанную страницу по различным маршрутам, то есть заранее не знаете маршрут, по которому можно вернуться.
Амир Сассон
112

В финальной версии Angular 2.x / 4.x - вот документы 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
  }
}
Hinrich
источник
1
При переходе к предыдущему экрану мы можем сохранить введенные значения без использования объекта в сервисе.
Vignesh
Как показать анимацию во время выполнения location.back ()?
Снегопады
50

<button backButton>BACK</button>

Вы можете поместить это в директиву, которая может быть присоединена к любому активному элементу:

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

Применение:

<button backButton>BACK</button>
hansmaad
источник
это потрясающе!
Рафаэль де Кастро
1
Если вы обновите страницу и нажмете кнопку «this.location.back ()», она просто запустит обновление страницы. Есть ли способ, которым модуль Location может определить, существует ли предыдущий путь?
Генри ЛоуЧ
хорошая работа, человек! ;)
elciospy
Имейте в виду, что если пользователь перешел непосредственно на страницу, где существует кнопка «Назад», и если он нажмет на кнопку…, он будет исключен из приложения на предыдущую страницу в соответствии с историей браузера (платформы).
hastrb
Для будущих читателей, посмотрите API документы
hastrb
24

Протестировано с Angular 5.2.9

Если вы используете якорь вместо кнопки вы должны сделать это пассивный канал с href="javascript:void(0)"сделать угловую Место работы.

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>
JavierFuentes
источник
Я бы предложил создать директиву clickPreventDefault вместо использования javascript:void(0). Нечто подобное ... @Directive({ selector: '[clickPreventDefault]' }) export class ClickPreventDefaultDirective { @HostListener("click", ["$event"]) onClick($event: Event) { $event.preventDefault(); } }
Бмд
Спасибо @bmd, это более сложный способ, но он тоже работает. Другое рабочее решение - не используйте herf: <a (click)="goBack()">, хотя этот способ не проходит HTML-валидаторы.
Хавьер Фуэнтес
20

Вы можете реализовать routerOnActivate()метод в своем классе маршрута, он будет предоставлять информацию о предыдущем маршруте.

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

Затем вы можете использовать router.navigateByUrl()и передавать данные, полученные из ComponentInstruction. Например:

this._router.navigateByUrl(prevInstruction.urlPath);
Sasxa
источник
Это все еще верно для Angular 2.1.0?
smartmouse
1
@ Smartmouse Я так не думаю, есть документация дляrouterOnActivate
Bojan Kogoj
4
Ссылка routerOnActivate () в этом ответе не работает. Кажется, это не способ сделать это в версии выпуска.
rmcsharry
14

Также работать для меня, когда мне нужно вернуться назад, как в файловой системе. PS @angular: "^ 5.0.0"

<button type="button" class="btn btn-primary" routerLink="../">Back</button>
Шевцов Андрей
источник
7
Я надеялся, что это сработает, но это вернется к следующему маршруту над ним, а не к маршруту, на котором вы были до перехода на страницу. Полезно знать, что это существует, но если у вас есть несколько точек входа для вашего компонента, этот метод будет когда-либо возвращаться только на маршрут выше него, а не туда, откуда вы исходили.
Скотт Байерс
Как я пишу "когда мне нужно вернуться назад, как в файловой системе" :) Для меня это поведение также было неожиданным.
Шевцов Андрей
12

Я сделал кнопку, которую можно использовать в любом месте моего приложения.

Создать этот компонент

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

Затем добавьте его в любой шаблон, когда вам нужна кнопка возврата.

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

Примечание: это использует Angular Material, если вы не используете эту библиотеку, удалите mat-buttonи color.

Тодд Скелтон
источник
Работает ли этот подход с именованными выходами маршрутизатора? Скажем, у меня есть несколько на странице, и я хочу вернуться только к одному из них, будет ли это работать?
RRD
Вам придется использовать другой подход в этой ситуации. Если у вас была одна и та же кнопка возврата в двух разных розетках маршрутизатора, они, вероятно, оба сделают одно и то же и вернутся к последней розетке маршрутизатора, которая была изменена.
Тодд Скелтон
Для названных точек, я обнаружил , что этот подход сработал: this.router.navigate ([ '../'], {relativeTo: this.route})
RRD
Как использовать этот компонент внутри другого компонента?
Р. Н. Кушваха
12

После всех этих удивительных ответов, я надеюсь, что мой ответ найдет кого-то и поможет им. Я написал небольшой сервис для отслеживания истории маршрутов. Здесь это идет.

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;
  }
}
Анжил Дхамала
источник
Попробовав более или менее все решения, я обнаружил, что это наиболее последовательный способ сделать это
А.
Что если я открою страницу по определенной ссылке и захочу, чтобы она вернулась на страницу в дереве страниц?
Иван
8

То, как я это делал при переходе на другую страницу, добавляет параметр запроса, передавая текущее местоположение

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

Прочитайте этот параметр запроса в вашем компоненте

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

Если returnUrl присутствует, включите кнопку «Назад» и когда пользователь нажимает кнопку «Назад»

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

Это должно быть в состоянии перейти на предыдущую страницу. Вместо использования location.back я чувствую, что вышеописанный метод более безопасен, рассмотрим случай, когда пользователь напрямую попадает на вашу страницу, и если он нажимает кнопку возврата с помощью location.back, он перенаправляет пользователя на предыдущую страницу, которая не будет вашей веб-страницей.

Пунит Рай
источник
Необходимо импортировать ActivatedRoute и использовать его вместо Router в подписке queryParams (например, this.route.queryParams.subscribe), но в остальном, похоже, работает!
Стивен Кайзер
для меня это работает нормально с самим маршрутизатором даже в угловых 4
Puneeth Rai
1
Лучший ответ, но в Angular 5 (до x?) Вам нужно внедрить объект «ActivatedRoute» и использовать queryParams для этого объекта, как уже сказал Стивен Кайзер.
Сатрия
8

В RC4:

import {Location} from '@angular/common';
Томаш Белава
источник
3

Чтобы вернуться без обновления страницы, мы можем сделать в html, как показано ниже : javascript: history.back ()

<a class="btn btn-danger" href="javascript:history.back()">Go Back</a>
Singhak
источник
Я бы порекомендовал использовать Locationсервис вместо этого. официальный API
hastrb
2

Начиная с бета 18:

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

Альберт
источник
2

Другое решение

window.history.back();

Джан Оперта
источник
У меня работает location.back () тоже работает, но не скомпилирую с --prod
Алекс