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

Javascript Angular 2如何使用router和location.go()检测后退按钮按下?,javascript,angular,angular-ui-router,Javascript,Angular,Angular Ui Router,我构建了一个应用程序,它使用router 3.0.0-beta.1在应用程序部分之间切换。我还使用location.go()模拟同一页面的子部分之间的切换。我使用了和一些URL重写规则,以便在页面刷新时将所有路由重定向到index.html。这允许路由器以URL参数的形式接收请求的子节。基本上,我已经设法避免使用HashLocationStrategy 路由。ts export const routes: RouterConfig = [ { path: '',

我构建了一个应用程序,它使用
router 3.0.0-beta.1
在应用程序部分之间切换。我还使用
location.go()
模拟同一页面的子部分之间的切换。我使用了
和一些URL重写规则,以便在页面刷新时将所有路由重定向到
index.html
。这允许路由器以URL参数的形式接收请求的子节。基本上,我已经设法避免使用
HashLocationStrategy

路由。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中没有散列…

使用事件完成了以下操作:

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

我同意Adrian Moisa的回答

但您可以通过向组件或服务注入类来使用“更具角度的2种方式”,然后您可以通过以下方式定义onPopState回调:

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

我不知道其他答案是否过时,但在第七章中,这两个答案都不适合我。我所做的是通过将角度事件侦听器导入到我的组件中来添加它:

import { HostListener } from '@angular/core';
然后在
窗口
对象上侦听
popstate
(按照Adrian的建议):


这对我很有效。

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

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

角度文档状态直接在PlatformLocation类中

  • 应用程序开发人员不应直接使用此类
我在构造函数中使用了LocationStrategy

constructor(location: LocationStrategy) {
  location.onPopState(() => {
    alert(window.location);
  });
}
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');
  });

此问题的另一个备选方案是订阅由发出的事件。因为我们正在处理路由问题,在我看来,使用路由器事件更有意义

constructor(router: Router) {
    router.events
      .subscribe((event: NavigationStart) => {
        if (event.navigationTrigger === 'popstate') {
          // Perform actions
        }
      });
}
我想指出的是,在浏览器上前后按时会出现
popstate
。所以为了有效地做到这一点,你必须找到一种方法来确定哪一个正在发生。对我来说,这只是使用了类型为的
事件
对象,它提供了有关用户来自何处以及他们将去何处的信息。

更简单的方法-


我真的不知道你的用例。这根线很旧了。但这是谷歌的第一次成功。如果其他人正在用Angular 2和ui路由器寻找这个(就像您正在使用的一样)

从技术上讲,它并没有检测到后退按钮。它更能检测作为开发人员的您是否触发了状态更改,或者用户是否自己更新了URL

您可以通过uiSref和stateService.go向状态更改添加自定义选项。在转换中,可以检查是否设置了此选项。(不会在点击后退按钮等时设置)

使用ui-sref

    <a uiSref="destination-name" [uiOptions]="{custom: {viaSref: true}}">Bar</a>
您可以在任何过渡钩子中检测到它,例如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?');
    }
}

这是Angular 11的最新更新

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

import { NavigationStart, Router } from '@angular/router';
然后将以下代码添加到构造函数中

constructor(location: LocationStrategy) {
  location.onPopState(() => {
    alert(window.location);
  });
}
constructor(private router: Router) {
  router.events.forEach((event) => {
    if(event instanceof NavigationStart) {
      if (event.navigationTrigger === 'popstate') {
        /* Do something here */
      }
    }
  });
}
您可以检查“window.history”的大小,如果大小为1,则无法返回

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

onPopState的问题是,即使用户继续,也会引发事件。这将为
窗口创建全局侦听器:使用
@HostListener
时,popstate
事件将仅在当前组件上侦听。PlatformLocation:“应用程序开发人员不应直接使用此类。”了解如何停止收听活动或取消订阅此活动。我尝试使用fromEvent(window,'popstate')并在那里取消订阅,但不起作用。你可以使用location.onPopState=()=>{}根据Angular的官方文档,PlatformLocation不应该由应用程序开发人员直接使用。我采用了这个解决方案,实际上更干净。我定义了订阅,然后在
ngOnInit
中执行
subscribe
,在
ngondestory
中执行
unsubscribe
。如果我使用移动设备并下拉屏幕并刷新页面,这会起作用吗?正如MDN所述:“每次活动历史记录条目在同一文档的两个历史记录条目之间发生更改时,都会向窗口发送一个popstate事件”。这意味着当用户单击“上一步”和“下一步”@indrajeet/*处理选项卡关闭/刷新事件/@HostListener('window:beforeunload',['$event']时,将触发该事件)unloadNotification($event:any){if(pendingTask()){/实现您的逻辑,确定您是否有任何挂起的任务*/return false;}否则{return false;}}}“最新“有棱角的版本对多年后提出这个问题的人没有帮助。很想让这本书说明你的实际版本。@SeanHalls我们当时在7号。我将更新答案。请欣赏关于需要进一步逻辑来确定前进和后退之间的转向。此答案看起来提供了更好的解决方案
isCanGoBack(){
    window.history.length > 1;
}