为了账号安全,请及时绑定邮箱和手机立即绑定

Chrome/Opera `window.onpopstate` 错误

Chrome/Opera `window.onpopstate` 错误

偶然的你 2023-08-18 17:04:46
我正在尝试处理window.onpopstate我的单页应用程序中的事件,但在 Google Chrome 和 Opera 中它不起作用。这是我的简单 html 页面<html>    <head>        <meta charset="utf-8" />        <script>        window.onpopstate = function(e) {            alert('onpopstate');        }        setTimeout(function () {            history.pushState(1, 'Hello John', '/hello/john');        }, 2000);        setTimeout(function () {            history.pushState(2, 'Hello Emily', '/hello/emily');        }, 3000);        </script>    </head>    <body></body></html>当我点击浏览器的后退按钮时,我希望看到带有onpopstate显示文本的警报。在 Safari、Firefox、Vivaldi 中,它按预期工作。在 Chrome 和 Opera 中,它从未调用过,它只是通过重新加载来转到上一页,这对我的 SPA 来说是一个糟糕的情况。更奇怪的是我发现了一些让它发挥作用的技巧:转到开发工具,控制台选项卡但是,如果我在有或没有超时的页面上的脚本中执行相同的操作,则此技巧根本不起作用。因此,我发现完成工作的唯一方法是手动转到控制台并执行。console.log(history)console.log(window)onpopstateconsole.log(history)也许我错过了什么?任何帮助,将不胜感激。我的环境:macOS 11.0.1 (20B29)Chrome 87.0.4280.67(官方版本)(x86_64)歌剧 72.0.3815.378解决方案:好吧,这不是一个错误,这是一个功能!这是interact firstChromium 的一个特性。如果用户首先以某种方式与页面交互,那么一切都会正常,否则back button将通过重新加载返回。例如,只需在正文中添加一些按钮并先单击它,然后尝试back在浏览器中单击。<body>     <button onclick="alert('hello');">alert</button>     </body>
查看完整描述

2 回答

?
慕后森

TA贡献1802条经验 获得超5个赞

为了能够运行一些 JavaScript,例如移动历史记录或播放声音或弹出窗口,用户首先必须在网站上进行交互(单击)。

查看完整回答
反对 回复 2023-08-18
?
互换的青春

TA贡献1797条经验 获得超6个赞

我在 MDN 上找到了一个注释。它说:

注意:调用history.pushState()或history.replaceState()不会触发popstate事件。popstate 事件仅通过执行浏览器操作来触发,例如在同一文档的两个历史记录条目之间导航时单击后退按钮(或在 JavaScript 中调用history.back())。

我建议您将事件处理程序注册到WindowEventHandlers 的 onpopstate 属性addEventListener(),而不是注册到WindowEventHandlers的onpopstate属性。

例子:

<html>

    <head>

        <meta charset="utf-8" />

        <script>

            // ref: https://developer.mozilla.org/en-US/docs/Web/API/Window/popstate_event

            window.addEventListener('popstate', function(e) {

                alert('onpopstate');

            }

            setTimeout(function () {

                history.pushState(1, 'Hello John', '/hello/john');

            }, 2000);

            setTimeout(function () {

                history.pushState(2, 'Hello Emily', '/hello/emily');

            }, 3000);

        </script>

    </head>

    <body></body>

</html>


查看完整回答
反对 回复 2023-08-18
?
慕斯王

TA贡献1864条经验 获得超2个赞

使用 anObject表示state

状态对象是一个 JavaScript 对象,与 PushState() 创建的新历史记录条目相关联。每当用户导航到新状态时,都会触发 popstate 事件,并且该事件的 state 属性包含历史记录条目的状态对象的副本。

const log = Logger();


// create 3 'history pages'

history.pushState({page: 1, greet: "Hello John"}, '', "#John");

history.pushState({page: 2, greet: "Hello Emily"}, '', "#Emily");

history.pushState({page: 3, greet: "Hello James"}, '', "#James");


log(`current history state: ${JSON.stringify(history.state)}`);


// on popstate log the history state if applicable

window.addEventListener("popstate", () =>

  history && history.state && log(`${history.state.greet || ""} @page ${

    history.state.page} (location: ${location.hash})`)

);


// listener for the buttons

document.addEventListener("click", evt => {

  if (evt.target.nodeName === "BUTTON") {

    return evt.target.id === "back" ? history.back() : history.forward();

  }

});


// helper function for logging in the document

function Logger() {

  let logEl;

  if (typeof window === "object") {

    logEl = document.querySelector("#log") || (() => {

      document.body.append(

        Object.assign(document.createElement('pre'), 

        {id: "log"}));

      return document.querySelector("#log");

    })();

    return (...logLines) => 

      logLines.forEach(s => logEl.textContent += `${s}\n`);

  } else {

    return (...logLines) => 

      logLines.forEach(ll => console.log(`* `, ll));

  }

}

<button id="back">&lt;&lt; 1 back</button>

<button id="forward">1 forward &gt;&gt;</button>


查看完整回答
反对 回复 2023-08-18
  • 2 回答
  • 0 关注
  • 114 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信