Angular 2 Как обнаружить кнопку "Назад" с помощью маршрутизатора и location.go()?

Я создал приложение, которое использует router 3.0.0-beta.1 для переключения между разделами приложения. Я также использую location.go() для эмуляции переключателя между подразделами одной и той же страницы. Я использовал <base href="/"> и несколько правил перезаписи URL, чтобы перенаправить все маршруты на index.html в случае обновления страницы. Это позволяет маршрутизатору получать запрошенный подраздел как параметр URL. В основном мне удалось избежать использования HashLocationStrategy.

routes.ts

export const routes: RouterConfig = [
    {
        path: '',
        redirectTo: '/catalog',
        pathMatch: 'full'
    },
    {
        path: 'catalog',
        component: CatalogComponent
    },
    {
        path: 'catalog/:topCategory',
        component: CatalogComponent
    },
    {
        path: 'summary',
        component: SummaryComponent
    }
];

Если я нажимаю на подраздел в навигационной панели 2, все происходит:

  • logation.go() обновляет URL-адрес необходимой строкой, чтобы указать текущий подраздел
  • Пользовательская анимация scrollTo() прокручивает страницу вверху запрошенного подраздела.

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

this._activatedRoute.params
    .map(params => params['topCategory'])
    .subscribe(topCategory => {
        if (typeof topCategory !== 'undefined' &&
            topCategory !== null
        ) {
            self.UiState.startArrowWasDismised = true;
            self.UiState.selectedTopCategory = topCategory;
        }
    });

Все работает отлично, за исключением случаев, когда я нажимаю кнопку "Назад". Если предыдущая страница была другим разделом, маршрутизатор приложений ведет себя так, как ожидалось. Однако, если предыдущая страница /url была подразделением, url изменяется на предыдущий, но ничего не происходит в пользовательском интерфейсе. Как определить, была ли нажата кнопка "Назад", чтобы вызвать функцию scrollTo() для повторной работы?

Большинство ответов, которые я видел, относятся к событию onhashchange, но это событие не запускается в моем приложении, так как у меня нет хеша в URL-адресе после...

Ответ 1

Я не знаю, датированы ли ответы, но ни один из них не помог мне в последней версии Angular. Я добавил обработчик событий Angular, импортировав его в свой компонент:

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

и затем прослушивание popstate на объекте window (как рекомендовал Адриан):

  @HostListener('window:popstate', ['$event'])
  onPopState(event) {
    console.log('Back button pressed');
  }

Это сработало для меня.

Ответ 2

Чтобы обнаружить кнопку назад, нажмите кнопку import platformlocation из '@ angular/common и поместите ниже код в свой конструктор:

 constructor(location: PlatformLocation) {
     location.onPopState(() => {
        alert(window.location);
     }); }

Ответ 3

Angular документация прямо в классе PlatformLocation...

  • Этот класс не должен использоваться непосредственно разработчиком приложения.

Я использовал LocationStrategy в конструкторе

constructor(location: LocationStrategy) {
  location.onPopState(() => {
    alert(window.location);
  });
}

Ответ 4

Я согласен с ответом Адриана Мойса,

но вы можете использовать "больше Angular 2 way", используя класс PlatformLocation, введя ваш компонент или услугу, затем вы можете определить обратный вызов onPopState следующим образом:

this.location.onPopState(()=>{
  // your code here...
  this.logger.debug('onpopstate event');
});

Ответ 5

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

constructor(router: Router) {
    router.events
      .subscribe((event: NavigationStart) => {
        if (event.navigationTrigger === 'popstate') {
          // Perform actions
        }
      });
}

Я хотел бы отметить, что popstate происходит при нажатии назад и вперед в браузере. Таким образом, чтобы сделать это эффективно, вам нужно будет найти способ определить, какой из них происходит. Для меня это было просто использование объекта event типа NavigationStart, который дает информацию о том, откуда приходит пользователь и куда он собирается.

Ответ 6

Отличный чистый способ - импортировать fromEvent из rxjs и использовать его таким образом.

fromEvent(window, 'popstate')
  .subscribe((e) => {
    console.log(e, 'back button');
  });

Ответ 7

Используя onpopstate событие получило трюк:

window.addEventListener('popstate',
    // Add your callback here
    () => self.events.scrollToTopCategory.emit({ categId: self.state.selectedTopCategory })
);