【问题标题】:Browser back button using React使用 React 的浏览器后退按钮
【发布时间】:2023-03-07 06:15:01
【问题描述】:

我正在使用 React。我想在用户点击后退按钮时警告用户。

我所做的是

handleWindowClose = (ev) => {
    ev.preventDefault();
    return ev.returnValue = 'Leaving this page will loose data';
}

componentDidMount = () => {
    window.addEventListener('beforeunload',this.handleWindowClose);
}

componentWillUnmount = () => {
    window.removeEventListener('beforeunload',this.handleWindowClose);
}

但是,这不适用于单击后退按钮。所以我尝试这样做:

handleWindowClose = (ev) => {
    ev.preventDefault();
    return ev.returnValue = 'Leaving this page will loose data';
}

onBackButtonEvent = (e) => {
    e.preventDefault();
    if (confirm("Do you want to loose this data")) {
        window.history.go(0);
    }
    else {
        window.history.forward();
    }
}

componentDidMount = () => {
    window.addEventListener('beforeunload',this.handleWindowClose);
    window.addEventListener('popstate',this.onBackButtonEvent);
}

componentWillUnmount = () => {
    window.removeEventListener('beforeunload',this.handleWindowClose);
    window.removeEventListener('popstate',this.onBackButtonEvent);
}

我没有使用 react-router。有没有更好的方法只使用 React 来做到这一点?此外,我希望窗口留在该页面上而不使用 history.forward(),因为我将失去窗口状态。

【问题讨论】:

  • 有什么理由不想使用react-router

标签: reactjs


【解决方案1】:

在 React 中处理后退按钮时遇到以下问题:

  1. 第一个 popstate 事件不是第一次被调用
  2. 执行我的后退按钮自定义逻辑后调用了两次

为了解决问题1,我做了以下代码:

componentDidMount() {
    window.history.pushState(null, null, window.location.pathname);
    window.addEventListener('popstate', this.onBackButtonEvent);
}

为了解决问题2,我做了以下代码:

onBackButtonEvent = (e) => {
    e.preventDefault();

    if (!this.isBackButtonClicked) {
        if (window.confirm("Do you want to save your changes")) {
            this.isBackButtonClicked = true;
            // Your custom logic to page transition, like react-router-dom history.push()
        }
        else {
            window.history.pushState(null, null, window.location.pathname);
            this.isBackButtonClicked = false;
        }
    }
}

不要忘记在构造函数中添加 this.isBackButtonClicked = false; 并取消订阅事件。

componentWillUnmount = () => {
    window.removeEventListener('popstate', this.onBackButtonEvent);
}

【讨论】:

    【解决方案2】:

    我遇到了类似的问题并以这种方式解决了这个问题:

    componentDidUpdate(){
      
        window.onpopstate  = (e) => {
            // Tour code...
        }      
    }
    

    【讨论】:

    • 另外,您可以在here.找到浏览器支持详情和简单示例
    【解决方案3】:

    试试这个代码:

    componentDidMount() {
        window.addEventListener("popstate", this.onBackButtonEvent)
    }
    
    componentWillUnmount() {
      window.removeEventListener("popstate", this.onBackButtonEvent)
    }
    
    onBackButtonEvent = () => {
        window.history.forward()
    }
    

    【讨论】:

      【解决方案4】:

      看起来onbeforeunload 是您想要的:检查此related question,其中包含useful demo

      另外the MDN documentation 包含一个有用的例子。


      假设您有充分的理由不想使用react-router,我将简要介绍一下 JavaScript 的实现方式

      您似乎捕获了错误的事件。您想获取 URL 哈希的任何更改,因此您应该使用 onhashchange

      文档中的示例:

      if ("onhashchange" in window) {
          alert("The browser supports the hashchange event!");
      }
      
      function locationHashChanged() {
          if (location.hash === "#somecoolfeature") {
              somecoolfeature();
          }
      }
      
      window.onhashchange = locationHashChanged;
      

      但是,鉴于您正在使用 React 进行开发,我愿意尝试 react-router。在这种情况下,browserHistory 将是您的朋友。

      【讨论】:

      • 我不是路由。我有一个向导排序的应用程序。用户单击下一步,我使用 ajax 获取下一个数据。所以这没有在浏览器历史记录中注册。但是当用户单击后退按钮,然后应用程序将他带出此向导。所以我不能使用 hashChange 所以我没有留下窗口的状态。所以即使我使用 history.forward。我将有一个新的状态并松开那个。因此,如果有一些优雅的方法可以像浏览器关闭事件一样做到这一点。
      • 使用 react-router..??这也不是一个选项,因为应用程序已经构建了
      • 似乎对我没有帮助。正如我之前提到的,我已经使用过这个事件。而且这不会在后退按钮上触发。它仅在刷新和窗口关闭事件时触发。跨度>
      • 我没看到你在哪里提到onbeforeunload。您使用不同的beforeunload。而且,您错了:onbeforeunload 确实 在单击后退按钮时触发。你真的检查过我在编辑中链接的演示吗? @dhrDatt
      • 我用过这个window.addEventListener('onbeforeunload',this.handleWindowClose);handleWindowClose = (ev) => { ev.preventDefault(); return ev.returnValue = 'Leaving this page will loose data'; }
      猜你喜欢
      • 2013-03-02
      • 2016-06-09
      • 1970-01-01
      • 2011-08-06
      • 1970-01-01
      • 2011-02-17
      • 1970-01-01
      • 2010-10-31
      相关资源
      最近更新 更多