【问题标题】:How to use history.pushState in conjunction with back functionality of the browser如何结合浏览器的后退功能使用 history.pushState
【发布时间】:2017-12-28 17:40:45
【问题描述】:

我使用history.pushState,它就像一个魅力,除了一个问题,如果你在 chromium 或 firefox 中点击“返回”,一旦正确操作了 url,url 会改变,但页面不会重新加载。

详细说明:

我们从mysite.tld开始

现在(经过一些用户交互)我们使用history.pushState 并将网址更改为mysite.tld/some/subpage。页面会相应地重新呈现。

现在,如果您点击“返回”,URL 会改变,但页面不会改变! 如果刷新,页面就会刷新。

我的天真(我是一个绝对的 javascript 菜鸟)是这样添加一个 eventListener:

dom.window.addEventListener("popstate",
  {
    (event: Event) =>
    {
      dom.window.location.reload()
    }
  })

但这当然有一些令人不快的副作用(每当 url 发生变化时,它都会重新加载页面。对于画廊或幻灯片等非常不利)

【问题讨论】:

  • 为什么要在 popstate 上重新加载页面?推送状态 API 的存在是为了反映 URL 中单页应用程序的变化。您推送的状态有两个影响:URL 可以共享和添加书签,并且在重新访问时 可以 在服务器端呈现(因此 URL 必须包含您的服务器在检索时重新建立内容所需的所有信息)。您写了“如果您点击“返回”,则 url 会更改,但页面不会更改”-您必须侦听该事件并更新页面内容 client side(通常通过通过 AJAX 请求数据并呈现内容)。
  • 这就是我想要做的,但是单独听“popstate”似乎太宽泛了。

标签: javascript browser-history scala.js


【解决方案1】:

pushstate 功能允许您在浏览器历史记录(URL、标题)中反映客户端应用程序的状态。

这是流程

  • 用户更改应用程序的状态
  • 应用程序更改历史状态
    • 设置代表应用程序状态的数据(例如显示的当前数据)
    • 设置 URL 以反映应用程序的状态
  • 用户导航(改变状态),触发popstate事件
    • 该事件包含一个state 属性,该属性是您在推送状态时设置的数据
    • 您根据状态更新应用程序的视图

看这个例子(注释解释):

popstate.html

<!DOCTYPE html>
<html>
<head>
    <title>Pushstate/Popstate</title>
</head>
<body>
    <a href="javascript: void(0)">increment</a>
    <div id="output">?</div>
    <script type="text/javascript">
        window.onload = function() {
            let identifier = 0,
                match,
                query,
                identifiererEl = document.getElementById("output");

            // - Since all URL properties can be accessed clientside, 
            //   the request data is extracted from the current URL.
            // - This can be seen like an ID that the server may use 
            //   to find the actual content
            // - Note that history.state makes no sense in this case, 
            //   since it is null when the script first runs.
            match = /identifier=(\d+)/.exec(location.search);

            // This emulates the behaviour of a server it won't make sense in 
            // a client side application
            if (match) {
                // Set the identifier with the data "from the server"
                identifier = Number(match[1]) || 0;
                // Make the view initially reflect the state
                render(identifier);
            }

            function render(text) {
                identifiererEl.textContent = text;
            }

            // Listen to user interaction to alter the data, render and 
            // push the state
            document.querySelector("a").addEventListener("click", (e) => {
                // Increment only for simplicity
                identifier++;

                render(identifier);

                history.pushState(
                    { identifier: identifier },
                    "",
                    `/popstate.html?identifier=${identifier}`
                );
            });

            // Listen to state changes to update the view
            window.addEventListener("popstate", (e) => {
                // Here you'd determine the actual data to render.
                // For simplicity the identifier itself is rendered.
                render(e.state.identifier);
            });
        };
    </script>
</body>
</html>

说到图库示例,identifier 可以是照片 ID,render() 可以更新图像的来源。当然,您负责获取所有或下一张/上一张照片(通过 AJAX 或内联到页面源中)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-12
    • 1970-01-01
    • 2014-05-10
    • 2023-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-29
    相关资源
    最近更新 更多