我正在用PHP做一个在线测试应用程序。我想限制用户在考试中返回。

我尝试了下面的脚本,但它停止了我的计时器。

我该怎么办?

定时器存储在cdtimer.js文件中。

<script type="text/javascript">
    window.history.forward();
    function noBack()
    {
        window.history.forward();
    }
</script>

<body onLoad="noBack();" onpageshow="if (event.persisted) noBack();" onUnload="">

我有一个考试计时器,它从一个MySQL值中获取考试的持续时间。计时器随之启动,但当我输入禁用后退按钮的代码时,它就停止了。我有什么问题?


当前回答

经历了大多数现有的答案,没有解决方案,工作在chrome。

这个想法是让浏览器在会话历史中向前移动一页,有效地防止使用后退浏览器按钮离开该页。通过调用History.forward()方法,在页面中放置下面的行,可以做到这一点。

window.history.forward();

我在mdn web docs找到了这个解决方案,它在chrome中工作。

其他回答

<html>
<head>
    <title>Disable Back Button in Browser - Online Demo</title>
    <style type="text/css">
        body, input {
            font-family: Calibri, Arial;
        }
    </style>
    <script type="text/javascript">
        window.history.forward();
        function noBack() {
            window.history.forward();
        }
    </script>
</head>
<body onload="noBack();" onpageshow="if (event.persisted) noBack();" onunload="">
    <H2>Demo</H2>
    <p>This page contains the code to avoid Back button.</p>
    <p>Click here to Goto <a href="noback.html">NoBack Page</a></p>
</body>
</html>

这是另一种方法。我们可以添加简短的SessionStorage条件,而不是仅仅尝试避免Back按钮功能(它不可靠地工作)。

假设我们有三个不同的页面(page1、page2和page3)。在每个页面上,我们都有一个链接,点击进入下一个页面,我们不希望用户能够回到上一页。

在第一个页面(page1.html),我们创建了一个SI (sessionStorage Item)与一个虚拟的“prev”代码和另一个与“page1”代码(SI“now”):

  PAGE 1  <button onclick="goto()">PAGE 2</button>

  -------------------

  let thispage = '1' // Or 123456 if preferred or make sense

  // You can replace this fixed 'thispage' value on each page with a script counting the clicks
  // or any other way to increase its value, i.e., thispage++
  // or what you want, even counting the url.length (lol)

  sessionStorage.setItem('prev', '0') // Dummy code
  sessionStorage.setItem('now', thispage)

  // You can here make this page unreachable with page2/page3 SI same conditions

  function goto(){
      window.location = "page2.html"
  }

在page2.html上,我们使用通常的NoBack脚本(如果它有效的话),只在来自page1时更新si:

  PAGE 2  <button onclick="goto()">PAGE 3</button>

  -------------------

  // If it works, let it work :-)

  history.pushState(null, null, location.href);
  history.back();
  history.forward();
  window.onpopstate = function () {
      history.go(1);
  };

  // else

  let thispage = '2' // 456789
  let thisprev = sessionStorage.getItem('now')
  if(sessionStorage.getItem('prev')==thispage) {
      console.log('USER is back on PAGE 2')
      setTimeout(function() { goto() }, 1000); // Remove log + setTimeout
  }
  if(thisprev !== thispage) {
      if(thisprev < thispage) {
          console.log('USER is coming from PAGE 1')
          sessionStorage.setItem('prev', thisprev)
          sessionStorage.setItem('now', thispage)
      }
      else {
          console.log('USER try to reload this page')
          setTimeout(function() { goto() }, 1000);
      }
  }

  function goto(){
      window.location = "page3.html"
  }

在page3.html上:

  PAGE 3  <button onclick="goto()">BACK TO PAGE 1</button>

  -------------------

  history.pushState(null, null, location.href);
  history.back();
  history.forward();
  window.onpopstate = function () {
      history.go(1);
  };

  let thispage = '3' // 999999
  let thisprev = sessionStorage.getItem('now')
  if(sessionStorage.getItem('prev') == thispage) {
      goto()
  }
  if(thisprev !== thispage) {
      if(thisprev < thispage) {
          sessionStorage.setItem('prev', thisprev)
          sessionStorage.setItem('now', thispage)
      }
      else {
          goto()
      }
  }
  function goto(){
      window.location = "page1.html" // Reinit test
  }

这样做的好处是,即使用户手动重新加载前一个页面(如果他有时间查看并记住URL),它仍然可以工作。它没有在所有设备上进行测试,但似乎在Firefox + Chrome + Edge Windows 10和Firefox + Chrome在OS X上运行良好。

这里的一些解决方案不会阻止回退事件的发生——它们让回退事件发生(浏览器内存中关于页面的数据丢失),然后它们播放一个向前事件,试图隐藏回退事件刚刚发生的事实。如果页面处于暂时状态,则该方法将不成功。

我为React写了这个解决方案(当React路由器不被使用时),它是基于vrfvr的答案。

它将真正阻止后退按钮做任何事情,除非用户确认弹出:

  const onHashChange = useCallback(() => {
    const confirm = window.confirm(
      'Warning - going back will cause you to loose unsaved data. Really go back?',
    );
    window.removeEventListener('hashchange', onHashChange);
    if (confirm) {
      setTimeout(() => {
        window.history.go(-1);
      }, 1);
    } else {
      window.location.hash = 'no-back';
      setTimeout(() => {
        window.addEventListener('hashchange', onHashChange);
      }, 1);
    }
  }, []);

  useEffect(() => {
    window.location.hash = 'no-back';
    setTimeout(() => {
      window.addEventListener('hashchange', onHashChange);
    }, 1);
    return () => {
      window.removeEventListener('hashchange', onHashChange);
    };
  }, []);

我觉得jordanhollinger.com上的这篇文章是最好的选择。与Razor的答案相似,但更清楚一些。下面的代码;全部归功于Jordan Hollinger:

页面:

<a href="/page-of-no-return.htm#no-back>You can't go back from the next page</a>

no return的JavaScript页面:

// It works without the History API, but will clutter up the history
var history_api = typeof history.pushState !== 'undefined'

// The previous page asks that it not be returned to
if ( location.hash == '#no-back' ) {
  // Push "#no-back" onto the history, making it the most recent "page"
  if ( history_api ) history.pushState(null, '', '#stay')
  else location.hash = '#stay'

  // When the back button is pressed, it will harmlessly change the url
  // hash from "#stay" to "#no-back", which triggers this function
  window.onhashchange = function() {
    // User tried to go back; warn user, rinse and repeat
    if ( location.hash == '#no-back' ) {
      alert("You shall not pass!")
      if ( history_api ) history.pushState(null, '', '#stay')
      else location.hash = '#stay'
    }
  }
}

我有这个问题与React(类组件)。

我很容易就解决了:

componentDidMount() {
    window.addEventListener("popstate", e => {
        this.props.history.goForward();
    }
}

我已经从react-router-dom中使用了HashRouter。