如何使用router和location.go()检测返回按钮按下

Angular 2 How to detect back button press using router and location.go()?

本文关键字:返回 检测 按钮 router 何使用 location go      更新时间:2023-09-26

我已经构建了一个应用程序,使用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
    }
];

如果我点击导航栏中的一个子栏,会发生两件事:

  • 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更改为前一个,但UI中没有任何变化。我如何检测后退按钮是否按下,以调用scrollTo()函数再次做它的工作?

我看到的大多数答案都依赖于事件onhashchange,但这个事件不会在我的应用程序中被触发,因为我在URL中没有散列。

我不知道其他答案是否过时了,但它们都不适合我在Angular 7中使用。我所做的就是将Angular的事件监听器导入到我的组件中:

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

,然后监听window对象上的popstate(如Adrian建议的):

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

解决这个问题的另一个方法是订阅Angular Router服务发出的事件。因为我们正在处理路由,在我看来,使用Router事件更有意义。

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

我想注意的是,popstate发生在按后退和向前在浏览器上。所以为了有效地做这个,你必须找到一种方法来确定哪个发生了。对我来说,那只是使用了类型为NavigationStart的event对象,它提供了关于用户从哪里来以及他们要去哪里的信息。

检测浏览器点击后退按钮从` @angular/common `导入platformlocation,并将以下代码放入构造函数中:

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

这是Angular 13的最新更新

你必须首先从angular路由器中导入NavigationStart

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

然后将以下代码添加到构造函数

constructor(private router: Router) {
  router.events.forEach((event) => {
    if(event instanceof NavigationStart) {
      if (event.navigationTrigger === 'popstate') {
        /* Do something here */
      }
    }
  });
}

一个很好的干净的方法是从rxjs中导入'fromEvent'并这样使用。

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

Angular文档直接在PlatformLocation类中声明…

  • 这个类不应该被应用程序开发人员直接使用。

我在构造函数

中使用了LocationStrategy
constructor(location: LocationStrategy) {
  location.onPopState(() => {
    alert(window.location);
  });
}

使用onpopstate事件达到了效果:

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

我同意Adrian Moisa的回答,

但是你可以使用"更多的Angular 2方式",使用类PlatformLocation注入到你的组件或服务中,然后你可以这样定义onPopState回调:

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

更简单的方式-链接

import { PlatformLocation } from '@angular/common';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
...
constructor(
private platformLocation: PlatformLocation ,
private modalService: NgbModal
)
{
platformLocation.onPopState(() => this.modalService.dismissAll());
}

我真的不知道你的用例。这条线很老了。但这是谷歌上的第一个点击率。如果有人在Angular 2和ui-router(就像你正在使用的)中寻找这个,

从技术上讲,它不能检测后退按钮。它更能检测到是你作为开发者触发了状态改变,还是用户自己更新了URL。

你可以添加自定义选项来改变状态,这可以通过uiSref和stateService.go来完成。在转换过程中,您可以检查是否设置了此选项。(点击后退键等不会设置)。

使用ui-sref

    <a uiSref="destination-name" [uiOptions]="{custom: {viaSref: true}}">Bar</a>
使用state.go

import {StateService} from '@uirouter/core';
...
@Component(...)
export class MyComponent {
    constructor(
        private stateService: StateService
    ) {}
    public myAction(): void {
        this.stateService.go('destination-name', {}, {custom: {viaGo: true}});
    }
}

你可以在任何转换钩子中检测到它,例如onSucces!

import {Transition, TransitionOptions, TransitionService} from '@uirouter/core';
...
@Component(...)
export class MyComponent implements OnInit {
    constructor(
        private transitionService: TransitionService
    ) {}
    public ngOnInit(): void {
        this.transitionService.onSuccess({}, (transition: Transition) => this.handleTransition(Transition));
    }
    private handleTransition(transition: Transition): void {
        let transitionOptions: TransitionOptions = transition.options();
        if (transitionOptions.custom?.viaSref) {
            console.log('viaSref!');
            return;
        }
        if (transitionOptions.custom?.viaGo) {
            console.log('viaGo!');
            return;
        }
        console.log('User transition?');
    }
}

您可以查看" window.history "的大小,如果大小为1则无法返回。

isCanGoBack(){
    window.history.length > 1;
}