Angular 2如何使用router和location.go()检测后退按钮按下?

Adr*_*isa 13 javascript angular-ui-router angular

我已经构建了一个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
    }
];
Run Code Online (Sandbox Code Playgroud)

如果我点击导航栏中的子部分,则会发生以下情况:

  • 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;
        }
    });
Run Code Online (Sandbox Code Playgroud)

除非单击后退按钮,否则一切正常.如果上一页是不同的部分,则应用程序路由器的行为与预期一致.但是,如果上一页/网址是子部分,则网址会更改为上一个网页,但UI中没有任何内容.如何检测后退按钮是否被按下以调用该scrollTo()功能再次执行它的工作?

我看到的大多数答案都依赖于事件onhashchange,但是这个事件在我的应用程序中没有被触发,因为我在URL中没有哈希值...

VSO*_*VSO 17

我不知道答案是否过时,但在Angular 2中它们都不适合我.我所做的是通过将Angular 2事件监听器导入我的组件来添加它:

import { HostListener } from '@angular/core';
Run Code Online (Sandbox Code Playgroud)

然后监听popstatewindow的对象(如阿德里安推荐):

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

此代码适用于最新的Angular 2.

  • 正如 MDN 所说:“每次活动历史条目在同一文档的两个历史条目之间发生变化时,都会将 popstate 事件分派到窗口”。这意味着当用户单击“后退”和“前进”时都会触发该事件 (2认同)
  • @SeanHalls 我们当时是 7 点。我会更新答案。 (2认同)

Nik*_*dav 14

这是 Angular 13 的最新更新

您必须首先从角度路由器导入NavigationStart

import { NavigationStart, Router } from '@angular/router';
Run Code Online (Sandbox Code Playgroud)

然后在构造函数中添加以下代码

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


Rya*_*lea 8

一个非常干净的方法是从 rxjs 导入 'fromEvent' 并以这种方式使用它。

fromEvent(window, 'popstate')
  .subscribe((e) => {
    console.log(e, 'back button');
  });
Run Code Online (Sandbox Code Playgroud)

  • 我采用了这个解决方案,确实干净得多。我定义了一个订阅,然后在“ngOnInit”中执行“subscribe”,并在“ngOnDestroy”中执行“unsubscribe”。 (2认同)

Shi*_* NH 7

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

 constructor(location: PlatformLocation) {
     location.onPopState(() => {
        alert(window.location);
     }); }
Run Code Online (Sandbox Code Playgroud)

  • 根据 Angular 的官方文档,应用程序开发人员不应直接使用 PlatformLocation。 (3认同)

Rma*_*moe 6

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

  • 此类不应由应用程序开发人员直接使用。

我在构造函数中使用了LocationStrategy

constructor(location: LocationStrategy) {
  location.onPopState(() => {
    alert(window.location);
  });
}
Run Code Online (Sandbox Code Playgroud)


Jon*_*ack 5

Another alternative for this issue would be to subscribe to the events emitted by the Angular Router service. Since we are dealing with routing, it seems to me that using Router events makes more sense.

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

I would like to note that popstate happens when pressing back and forward on the browser. So in order to do this efficiently, you would have to find a way to determine which one is occurring. For me, that was just using the event object of type NavigationStart which gives information about where the user is coming from and where they are going to.

  • 欣赏需要进一步的逻辑来确定前进和后退的指导 (2认同)