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

Что-то вроде

this._router.navigate(LASTPAGE);

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

  • Страница A -> Страница C, щелкните по ней, вернитесь на страницу A.

  • Страница B -> Страница C, щелкните по ней, вернитесь на страницу B.

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

Hongbo Miao

Ответов: 19

Ответы (19)

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

Здесь (в TypeScript):

импорт {Component} из '@ angular / core';
импортировать {Местоположение} из '@ angular / common';

@Компонент({
  // здесь объявления компонентов
})
class SomeComponent {

  конструктор (частный _location: Location)
  {}

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

Изменить: как указано в @ charith.arumapperuma Местоположение должно быть импортировано из @ angular / common, поэтому импортирует {Location} из ' @ angular / common '; важна строка.

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

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

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

Go Back

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


я использую таким образом:

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

@Component({
    selector: 'Back_page',
    template: ``,
})
export class BackPageComponent {
  constructor(private location: Location) { }

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

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

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

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

this._router.navigateByUrl(prevInstruction.urlPath);

в angular 4 используйте preserveQueryParams, например:

url: /list?page=1


При переходе по ссылке вы перенаправляетесь на edit / 10? Page = 1с сохранением параметров

ссылка: https://angular.io/docs/ts/latest/guide/router.html#! # Link-parameters-array

Также вы можете использовать эту услугу с функцией возврата в случае, если история пуста

url-back.service.ts

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

import { Router } from '@angular/router';

const EMPTY_HISTORY_LENGTH = 2;

/**
 * This service helps to Navigate back to the prev page, and if no prev page,
 * will redirect to the fallback url.
 */
@Injectable()
export class UrlBackService {
  constructor(private router: Router, private location: Location) {}

  /**
   * This method will back you to the previous page,
   * if no previous page exists, will redirect you to the fallback url.
   * @param href - url, if tryNativeFirst is provided, this is fallback url
   * @param tryNativeFirst - try to go back natively using browser history state.
   */
  back(href: string, tryNativeFirst: boolean = false) {
    if (tryNativeFirst) {
      if (history.length === EMPTY_HISTORY_LENGTH) {
        this.router.navigate(UrlBackService.urlToArray(href));
      } else {
        this.location.back();
      }
    } else {
      this.router.navigate(UrlBackService.urlToArray(href));
    }
  }

  /**
   * In case that router.navigate method tries to escape all '/' in the string,
   * was decided to split string to array, and if URL starts or ends with slash - remove them, eg:
   * /my/url will be split to ['', 'my', 'url'], so we need to remove empty spaces use filter function.
   * @param href
   * @private
   */
  private static urlToArray(href: string) {
    return href.split('/').filter((notEmpty) => notEmpty);
  }
}

url-back.service.spec.ts

import { TestBed } from '@angular/core/testing';

import { UrlBackService } from './url-back.service';
import { Router } from '@angular/router';
import { Location } from '@angular/common';
import { RouterTestingModule } from '@angular/router/testing';

describe('UrlBackService', () => {
  let service: UrlBackService;
  let router: Router;
  let location: Location;

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [RouterTestingModule],
      providers: [UrlBackService],
    });
    service = TestBed.inject(UrlBackService);
    router = TestBed.inject(Router);
    location = TestBed.inject(Location);
  });

  it('should be created', () => {
    expect(service).toBeTruthy();
  });

  it('no meter what history state is, it should be redirected to the /my/url', () => {
    spyOn(router, 'navigate');
    service.back('/my/url');
    expect(router.navigate).toHaveBeenCalledWith(['my', 'url']);
  });

  it('in case history is empty push to /my/url', () => {
    spyOn(router, 'navigate');
    service.back('/my/url', true);
    expect(router.navigate).toHaveBeenCalledWith(['my', 'url']);
  });

  it('in case history is NOT empty push to url1', () => {
    spyOn(location, 'back');
    window.history.pushState(null, '', 'url1');

    service.back('/my/url', true);
    expect(location.back).toHaveBeenCalled();
  });
});

In the final version of Angular 2.x / 4.x - here's the docs https://angular.io/api/common/Location

/ * машинописный текст * /

импортировать {Местоположение} из '@ angular / common';
// импортируем сюда материал

@Компонент({
// объявляем компонент здесь
})
export class MyComponent {

  // вставляем местоположение в конструктор компонента
  конструктор (частное местоположение: Местоположение) {}

  отменить() {
    this.location.back (); // <- вернуться в предыдущее место при отмене
  }
}

<кнопка backButton> НАЗАД

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

импорт {Директива, HostListener} из '@ angular / core';
импортировать {Местоположение} из '@ angular / common';

@Directive ({
    селектор: '[backButton]'
})
экспортный класс BackButtonDirective {
    конструктор (частное местоположение: Местоположение) {}

    @HostListener ('щелкнуть')
    по щелчку() {
        this.location.back ();
    }
}

Использование:

<кнопка backButton> НАЗАД 

да, ты справишься. напишите этот код на свой машинописный компонент и наслаждайтесь!

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

@Component({
    selector: 'return_page',
    template: ``,
})
export class ReturnPageComponent {
  constructor(private location: Location) { }

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

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

импорт {Location} из 'angular2 / platform / common';

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

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, он перенаправляет пользователя на предыдущую страницу, которая не будет вашей веб-страницей.

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

Вот как я это проверяю:

импорт {Component} из '@ angular / core';
импортировать {ActivatedRoute, Router} из '@ angular / router';
импортировать {Местоположение} из '@ angular / common';

@Компонент({
  селектор: 'app-foo',
  шаблон: ''
})
экспортный класс FooComponent {

  частный только для чтения canGoBack: boolean;

  конструктор(
    частный маршрут только для чтения: ActivatedRoute,
    частный маршрутизатор только для чтения: Маршрутизатор,
    частное местоположение только для чтения: Местоположение
  ) {
    // Здесь выполняется проверка. Обязательно сделай это
    // здесь в конструкторе, иначе `getCurrentNavigation ()`
    // вернет null.
    this.canGoBack = !! (this.router.getCurrentNavigation () ?. previousNavigation);
  }

  goBack (): void {
    if (this.canGoBack) {
      // Мы можем безопасно вернуться в предыдущее место как
      // мы знаем, что это в нашем приложении.
      this.location.back ();
    } еще {
      // Предыдущей навигации нет.
      // Здесь мы решаем, куда идти. Например, скажем,
      // верхний уровень - это индексная страница, поэтому мы поднимаемся на один уровень вверх.
      this.router.navigate (['..'], {relativeTo: this.route});
    }
  }

}

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

Это не без оговорок:

  • canGoBack будет ложным, даже если предыдущее местоположение действительно находится в нашем приложении , но страница была обновлена.
  • Пользователь может захотеть «вернуться» на предыдущую страницу (где возникла goBack ()), нажав кнопку «Назад» в браузере, но поскольку приложение вернулось в историю вместо того, чтобы нажимать новую местоположение, пользователь вернется еще дальше и может запутаться.

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

window.history.back ();

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

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

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

@Component({
    selector: 'back-button',
    template: ``,
})
export class BackButtonComponent {
    @Input()color: string;

  constructor(private location: Location) { }

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

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


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

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

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

app.component.ts

импорт {Component} из '@ angular / core';
импортировать {Местоположение} из '@ angular / common';

@Компонент({
  селектор: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {

  конструктор (частное местоположение: Местоположение) {
  }

  возвращаться() {
    // window.history.back ();
    this.location.back ();

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

app.component.html



  <-Назад

В RC4:

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

Please make sure you explicitly import if you are using latest Angular/TypeScript

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

и

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

2022 WebDevInsider