【问题标题】:history.replaceState() example?history.replaceState() 例子?
【发布时间】:2012-10-01 16:33:45
【问题描述】:

谁能给出history.replaceState 的工作示例?这就是w3.org 所说的:

history.replaceState(data, title [, url ] )

更新会话历史记录中的当前条目,使其具有给定的数据、标题和 URL(如果提供且不为空)。


更新

这很好用:

history.replaceState( {} , 'foo', '/foo' );

网址正在更改,但标题未更改。这是一个错误还是我错过了什么?在最新的 Chrome 上测试。

【问题讨论】:

  • 我一般不会推送 JavaScript 问题的附加库,但在这种情况下我会破例。 History.js 库是一个小型 shim,它可以清除现代浏览器中 History API 中的许多奇怪的不当行为。它甚至为旧版本的 IE 提供可选支持。
  • MDN 在Manipulating the browser history 上有一篇不错的文章
  • @Pointy history.js 效果很好。我已经更新了我的问题中的代码。不,我的问题是我无法使用浏览器后退按钮返回上一页
  • 根据Mozillatitle参数实际上并没有使用。
  • 第一个答案真的不应该是接受的答案,因为问题要求提供replaceState 示例,而接受的答案绝不是replaceState 示例。

标签: javascript ajax html


【解决方案1】:

这是一个最小的、人为的例子。

console.log( window.location.href );  // whatever your current location href is
window.history.replaceState( {} , 'foo', '/foo' );
console.log( window.location.href );  // oh, hey, it replaced the path with /foo

replaceState() 还有更多内容,但我不知道您到底想用它做什么。

【讨论】:

  • url 正在改变,但标题没有改变.. 用最新的 chrome @trott 测试
  • @Serjas 据我所知,replaceState() 中的 title 参数在所有浏览器中都被忽略了。
  • 标题在 safari 中不会被忽略,如果我是正确的github.com/whatwg/html/issues/2174
【解决方案2】:

确实这是一个错误,尽管现在已经有 2 年的时间了。 问题在于一些不清楚的规范以及涉及document.title 和后退/前进时的复杂性。

请参阅 WebkitMozilla 上的错误参考。 Opera 还引入了 History API said it wasn't using the title parameter 并且可能还没有。

目前 pushState 和 replaceState 的第二个参数——标题 历史条目的 - 不在 Opera 的实现中使用,但可以 有一天。

可能的解决方案

我看到的唯一方法是更改​​标题元素并改用 pushState:

document.getElementsByTagName('title')[0].innerHTML = 'bar';
window.history.pushState( {} , 'bar', '/bar' );

【讨论】:

  • 对于 jquery 用户.. 试试 $("title").html(_title);
  • 这可能会导致用户需要“双击”后退按钮,具体取决于您的实现方式。一个更简单的解决方案可能是继续使用replaceState() 并简单地手动设置文档标题document.title = "title"
【解决方案3】:

看例子

window.history.replaceState({
    foo: 'bar'
}, 'Nice URL Title', '/nice_url');

window.onpopstate = function (e) {
    if (typeof e.state == "object" && e.state.foo == "bar") {
        alert("Blah blah blah");
    }
};

window.history.go(-1);

然后搜索location.hash

【讨论】:

    【解决方案4】:

    history.pushState当前 页面状态推送到历史堆栈,并更改地址栏中的 URL。因此,当您返回时,该状态(您传递的对象)会返回给您。

    目前,仅此而已。任何其他页面操作,例如显示新页面或更改页面标题,都必须由您完成。

    您链接的 W3C 规范只是一个草稿,浏览器可能会以不同的方式实现它。例如,Firefox 完全忽略了title 参数。

    这是我在我的网站上使用的pushState 的一个简单示例。

    (function($){
        // Use AJAX to load the page, and change the title
        function loadPage(sel, p){
            $(sel).load(p + ' #content', function(){
                document.title = $('#pageData').data('title');
            });
        }
    
        // When a link is clicked, use AJAX to load that page
        // but use pushState to change the URL bar
        $(document).on('click', 'a', function(e){
            e.preventDefault();
            history.pushState({page: this.href}, '', this.href);
            loadPage('#frontPage', this.href);
        });
    
        // This event is triggered when you visit a page in the history
        // like when yu push the "back" button
        $(window).on('popstate', function(e){
            loadPage('#frontPage', location.pathname);
            console.log(e.originalEvent.state);
        });
    }(jQuery));
    

    【讨论】:

    • 为什么接受的答案解释“pushState”而不是“replaceState”?
    • @GiwrgosTsopanoglou:我在一年前回答了这个问题,所以我不知道为什么:-P 无论如何,replaceState 改变了当前页面状态。它允许您更改 当前 页面状态的状态对象和 URL。
    • 奇怪的是,我一直在寻找有关 replaceState 的信息,结果却阅读了有关 pushState 的信息:P
    【解决方案5】:

    第二个参数 Title 并不意味着页面的标题 - 它更多的是该页面状态的定义/信息

    但是我们仍然可以使用 onpopstate 事件来更改标题,并且不是从第二个参数传递标题名称,而是作为第一个参数作为对象传递的属性

    参考: http://spoiledmilk.com/blog/html5-changing-the-browser-url-without-refreshing-page/

    【讨论】:

      【解决方案6】:

      根据MDN History doc
      明确表示第二个参数是用于未来而不是现在。没错,第二个参数是处理网页标题,但目前所有主要浏览器都忽略了它。

      Firefox 目前会忽略此参数,但将来可能会使用它。在此处传递空字符串应该可以安全地防止将来对该方法进行更改。或者,您可以为您要迁移到的州传递一个简短的标题。

      【讨论】:

      • 第二个参数 not 指的是网页的标题 — 您链接的 MDN 文档说 "pass a您要迁移到的州的简短标题。”。这与 W3C history interface 文档中的说法一致,“将给定的数据推送到具有给定标题的会话历史记录中,”。该短语中的数据是 state 数据,因此标题再次引用状态(数据)。
      【解决方案7】:

      我真的很想回复@Sev 的回答。

      Sev 是对的,window.history.replaceState 内部有一个错误

      要解决这个问题,只需重写构造函数以手动设置标题。

      var replaceState_tmp = window.history.replaceState.constructor;
      window.history.replaceState.constructor = function(obj, title, url){
          var title_ = document.getElementsByTagName('title')[0];
          if(title_ != undefined){
              title_.innerHTML = title;
          }else{
              var title__ = document.createElement('title');
              title__.innerHTML = title;
              var head_ = document.getElementsByTagName('head')[0];
              if(head_ != undefined){
                  head_.appendChild(title__);
              }else{
                  var head__ = document.createElement('head');
                  document.documentElement.appendChild(head__);
                  head__.appendChild(title__);
              }
          }
          replaceState_tmp(obj,title, url);
      }
      

      【讨论】:

      • 不要那样做。覆盖默认函数是一种非常糟糕的风格
      • 当您需要修复此错误时,您还有什么建议?
      • @GlennPlas 针对 react repo 打开一个 PR :)
      【解决方案8】:

      假设https://www.mozilla.org/foo.html 执行以下JavaScript:

      const stateObj = { foo: 'bar' };
      
      history.pushState(stateObj, '', 'bar.html');
      

      这将导致 URL 栏显示 https://www.mozilla.org/bar2.html,但不会导致浏览器加载 bar2.html,甚至不会检查 bar2.html 是否存在。

      【讨论】:

        【解决方案9】:

        将其视为 URL:http://localhost:4200/inspections/report-details/60c88e4e76b14c00193f5bef

        let reportId = '60c88e4e76b14c00193f5bef', scope = "dynamic"
        
        window.history.replaceState(null, null, `inspections/report-details/${reportId}?damagePart=` + scope );
        

        这将产生输出 http://localhost:4200/inspections/report-details/60c88e4e76b14c00193f5bef?damagePart=dynamic/

        【讨论】:

          猜你喜欢
          • 2016-10-18
          • 2014-10-12
          • 1970-01-01
          • 2018-10-12
          • 1970-01-01
          • 2012-02-10
          • 2015-01-03
          • 2020-09-13
          • 2011-07-05
          相关资源
          最近更新 更多