簡體   English   中英

Angular 2 如何使用路由器和 location.go() 檢測后退按鈕按下?

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

我構建了一個應用程序,它使用router 3.0.0-beta.1在應用程序部分之間切換。 我還使用location.go()來模擬同一頁面的子部分之間的切換。 我使用了<base href="/">和一些 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()函數再次完成它的工作?

大多數的回答我relly看到了事件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對象,它提供有關用戶來自哪里以及他們要去哪里的信息。

要檢測瀏覽器后退按鈕,請單擊 import platformlocation from '@angular/common 並將以下代碼放入您的構造函數中:

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

Angular 文檔直接在 PlatformLocation 類中聲明...

  • 應用程序開發人員不應直接使用此類。

我在構造函數中使用了 LocationStrategy

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

一個非常干凈的方法是從 rxjs 導入 'fromEvent' 並以這種方式使用它。

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

這是 Angular 11 的最新更新

您必須首先從角度路由器導入 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 */
      }
    }
  });
}

使用onpopstate事件可以解決問題:

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

我同意 Adrian Moisa 的回答,

但是您可以通過注入到您的組件或服務中使用類PlatformLocation來使用“更多 Angular 2 方式”,然后您可以通過這種方式定義 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;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM