如何在Angular 2中禁用浏览器后退按钮

Posted

技术标签:

【中文标题】如何在Angular 2中禁用浏览器后退按钮【英文标题】:How to disable Browser back button in Angular 2 【发布时间】:2016-07-21 07:29:08 【问题描述】:

我正在使用 Angular 2 开发一个网站。 有没有办法使用 Angular 2 禁用或触发浏览器后退按钮?

谢谢

【问题讨论】:

window.history.back() ? 可能重复how to stop browser back button using javascript 【参考方案1】:

我在所有主要浏览器中使用和工作的代码段!

ngOnInit() 
   history.pushState(null, null, location.href);

   this.subscription = fromEvent(window, 'popstate').subscribe(_ => 
      history.pushState(null, null, location.href);
      this.openModal(`You can't make changes or go back at this time.`, 'Okay');
   );


ngOnDestroy() 
   this.subscription.unsubscribe();

【讨论】:

【参考方案2】:

这很简单,使用以下代码,此示例代码来自普通的 javascript,我已将其转换为 angular,并在我的 2-3 个项目中使用

// Inject LocationStrategy Service into your component
    constructor(
        private locationStrategy: LocationStrategy
      )  


// Define a function to handle back button and use anywhere
    preventBackButton() 
        history.pushState(null, null, location.href);
        this.locationStrategy.onPopState(() => 
          history.pushState(null, null, location.href);
        )
      

您也可以在任何服务中定义 preventBackButton 并从那里调用它

【讨论】:

这会在 Safari 上导致很多错误:“每 30.000000 秒尝试使用 history.pushState() 超过 100 次” 可能有一些代码在重复运行。我不确定确切的原因是什么。您能否在此处粘贴导致此错误的代码或错误的一些屏幕截图。【参考方案3】:

尝试使用这个

window.onpopstate = function (e)  window.history.forward(1); 

【讨论】:

有趣的 vanilla-JS 解决方案,尽管有人问过 Angular2+。您能否解释您的解决方案或添加指向文档的链接,例如:WindowEventHandlers.onpopstate - Web APIs | MDN【参考方案4】:

如果您希望禁用 angular(7/8/9/10) 中的浏览器后退按钮...试试这个链接并使用 npm 安装包。

1) npm install --save angular-disable-browser-back-button
2) import  NgModule  from '@angular/core';
import  BackButtonDisableModule  from 'angular-disable-browser-back-button';
 
@NgModule(
  ...
  imports: [
    ...
    BackButtonDisableModule.forRoot()
  ],
  ...
)
export class AppModule 

3)  BackButtonDisableModule.forRoot(
      preserveScrollPosition: true
    )

请使用下面给出的这个链接。参考取自。

[https://www.npmjs.com/package/angular-disable-browser-back-button][1]

【讨论】:

【参考方案5】:

我已经尝试了上面提到的所有解决方案,但没有一个适合我。经过两天的失败尝试,我终于找到了这个 npm 模块,它可以立即完美地工作。

Github:https://github.com/Zatikyan/angular-disable-browser-back-button#readme

【讨论】:

【参考方案6】:

在组件的 TS 文件中添加以下代码,您不想返回。

  @HostListener('window:hashchange', ['$event'])
  hashChangeHandler(e) 
    window.location.hash = "dontgoback";
  

【讨论】:

【参考方案7】:
import  LocationStrategy  from '@angular/common';
constructor( private location: LocationStrategy)  
// preventing back button in browser implemented by "Samba Siva"  
 history.pushState(null, null, window.location.href);  
this.location.onPopState(() => 
  history.pushState(null, null, window.location.href);
);  

它在 angular2/4/5 中对我 100% 工作正常

【讨论】:

即使在 Angular 11 中也能工作(仅在 chrome 中测试) 不,它在 Angular 11 中对我不起作用,它说,“'null' 类型的参数不能分配给 'string' 类型的参数” @Satrughna 你可以试试这个,它对我来说很好用:history.pushState(null, "null", window.location.href);【参考方案8】:

这个问题出现在 IE 浏览器上。使用下面提到的代码它将解决您的问题。


        @HostListener('document:keydown', ['$event'])
          onKeyDown(evt: KeyboardEvent) 
            if (
                evt.keyCode === 8 || evt.which === 8
            ) 
              let doPrevent = true;
              const types =['text','password','file','search','email','number','date','color','datetime','datetime-local','month','range','search','tel','time','url','week'];
              const target = (<htmlInputElement>evt.target);

          const disabled = target.disabled || (<HTMLInputElement>event.target).readOnly;
          if (!disabled) 
            if (target.isContentEditable) 
              doPrevent = false;
             else if (target.nodeName === 'INPUT') 
              let type = target.type;
              if (type) 
                type = type.toLowerCase();
              
              if (types.indexOf(type) > -1) 
                doPrevent = false;
              
             else if (target.nodeName === 'TEXTAREA') 
              doPrevent = false;
            
          


        if (doPrevent) 
            evt.preventDefault();
            return false;
          

        
    

【讨论】:

【参考方案9】:

也许有点晚,但也许有人可以使用它。 这是我用于带有选项卡(Bootstrap 4 样式)的页面的解决方案,其中每个选项卡都是一个组件。

    @Injectable()
    export class CanNavigateService 

      private static _isPermissionGranted = true
      public navigationAttempt = new Subject<boolean>()

      //-------------------------------------------------------------//

      /**Will the next navigation attempt be permitted? */
      updatePermission(isPermissionGranted: boolean)    
        CanNavigateService._isPermissionGranted = isPermissionGranted
      //updatePermission

      //-------------------------------------------------------------//

      /**Broadcast the last attempt and whether it was permitted */
      updateNavigationAttempt(wasPermissionGranted: boolean)     
        this.navigationAttempt.next(wasPermissionGranted)
      //updatePermission

      //-------------------------------------------------------------//

      /**Can we navigate? */
      public isPermissionGranted(): boolean 
        return CanNavigateService._isPermissionGranted
      //isPermissionGranted

    //Cls

NavigationGuard 类似于上面的@Jithin Nair,但也会广播何时尝试导航以及是否允许。 CanNavigateService 的订阅者可以使用它来决定做什么而不是返回导航。

@Injectable()
export class NavigationGuard implements CanDeactivate<any> 

constructor(private canNavigateService: CanNavigateService)  

//--------------------------------------------------------------------//

// will prevent user from going back if permission has not been granted
canDeactivate(component: any) 

    let permitted = this.canNavigateService.isPermissionGranted()
    this.canNavigateService.updateNavigationAttempt(permitted)        

    if (!permitted) 
        // push current state again to prevent further attempts.
        history.pushState(null, null, location.href)
        return false
    

    return true

//canDeactivate

//Cls

用法:

constructor(private _navigateService: CanNavigateService) 
    super()

    _navigateService.navigationAttempt.subscribe(wasPermitted => 
        //If navigation was prevented then just go to first tab
        if (!wasPermitted)
           this.onTabSelected( this._firstTab)            
    )
//ctor

//----------------------------------------------------------------------------//

onTabSelected(tab) 

    this._selectedTab = tab
    //If it's not the first tab you can't back navigate
    this._navigateService.updatePermission(this._selectedTab == this._firstTab)
//onTabSelected

【讨论】:

【参考方案10】:

第 1 步: 从 angular commmon 导入 Locatoion

import Location from "@angular/common";

第二步:在构造函数中初始化

private location: Location

步骤 3:在相应组件的 ngOnInit 中添加函数,

this.location.subscribe(currentLocation => 
if (currentLocation.url === '*/basic-info*') 
    window.onpopstate = function (event) 
        history.go(1);
    

);

注意:这里 /basic-info 将被您的路径替换。

如果第一次不起作用,请尝试添加外部订阅,

let currentUrl = window.location.href;
let tmpVar = currentUrl.includes('/basic-info');
if (currentUrl.includes('/basic-info')) 
  window.onpopstate = function (event) 
    history.go(1);
  

【讨论】:

【参考方案11】:

不确定这是否已经排序,但仍然发布答案,以供将来参考。 为了解决这个问题,您基本上需要在您的应用程序组件中添加一个侦听器并在您的角度路由器上设置一个canDeactivate 保护。

// in app.component.ts
import  LocationStrategy  from '@angular/common';

@Component(
  selector: 'app-root'
)
export class AppComponent 
  constructor(
    private location: LocationStrategy
  ) 
    // check if back or forward button is pressed.
    this.location.onPopState(() => 
      // set isBackButtonClicked to true.
      this.someNavigationService.setBackClicked(true);
      return false;
    );
  


// in navigation guard
@Injectable()
export class NavigationGuard implements CanDeactivate<any> 
  constructor(private someNavigationService: SomeNavigationService) 
  canDeactivate(component: any) 
    // will prevent user from going back
    if (this.someNavigationService.getBackClicked()) 
      this.someNavigationService.setBackClicked(false);
      // push current state again to prevent further attempts.
      history.pushState(null, null, location.href);
      return false;
    
    return true;
  

【讨论】:

this.someNavigationService.setBackClicked() 这个方法的定义/实现是什么? @Vinod 该方法只是根据发送的参数将标志更新为真或假。该服务基本上带有一个用于告诉您是否单击后退按钮的标志的设置器和获取器。单击后退/前进按钮将其设置为 true,然后在处理后重置为 false。 @JithinNair 请也为 SomeNavigationService 编写代码。【参考方案12】:

如果您想阻止到达某个路由,您可以将 @CanActivate() 装饰器添加到您的路由组件中

@Component(selector: 'control-panel-cmp', template: `<div>Settings: ...</div>`)
@CanActivate(checkIfWeHavePermission)
class ControlPanelCmp 

另请参阅 - Angular 2: Inject a dependency into @CanActivate? 用于访问全球服务。 - Angular2 Router - Anyone know how to use canActivate in app.ts so that I can redirect to home page if not logged in

【讨论】:

【参考方案13】:

试试这个

<script type = "text/javascript" >
history.pushState(null, null, 'pagename');
window.addEventListener('popstate', function(event) 
history.pushState(null, null, 'pagename');
);
</script>

将'pagename'更改为您的页面名称并将其放入页面的头部。

【讨论】:

【参考方案14】:

这不是 Angular2 相关的问题。您可以将用户发送回历史记录。具体见Manipulating the browser history、history.go()方法:

window.history.go(-1);

但是,我认为没有办法取消或禁用在浏览器窗口中按下后退按钮时的默认浏览器操作,因为这很容易被滥用。

您也可以在用户尝试离开页面时显示一个对话窗口:javascript before leaving the page

【讨论】:

onbeforeunload 不会在 Angular 的后退按钮上触发。

以上是关于如何在Angular 2中禁用浏览器后退按钮的主要内容,如果未能解决你的问题,请参考以下文章

关于 Angular 应用对浏览器 Back 按钮支持问题的讨论

如何禁用浏览器后退按钮..? [复制]

如何用jQuery禁用浏览器的前进后退按钮

如何使用 JavaScript 禁用浏览器中的后退按钮 [重复]

如何使用 JavaScript 禁用浏览器中的后退按钮 [重复]

如何使用 JavaScript 禁用浏览器中的后退按钮 [重复]