历史 API pushState() 创建两个条目

Posted

技术标签:

【中文标题】历史 API pushState() 创建两个条目【英文标题】:History API pushState() creating two entries 【发布时间】:2017-02-06 17:33:43 【问题描述】:

正如标题所述,当我使用 pushState() 更改历史记录时,它会出于某种原因将我的条目两次添加到堆栈中,即使它只单击了一次。因此,当我尝试使用后退按钮返回时,每隔一次按下按钮,我就会得到一个弹出状态。当我将状态记录到控制台时,每当我收到“pop”时,它都会显示“null”。

这就是历史的样子:

http://example.com/foo/bar/question/8/
http://example.com/foo/bar/question/8/
http://example.com/foo/bar/question/3/
http://example.com/foo/bar/question/3/
http://example.com/foo/bar/question/27/
http://example.com/foo/bar/question/27/

我想要做的是在链接点击时重新加载 iframe(并更改 h1 文本)而不重新加载整个页面,但仍然具有可遍历和可收藏的历史记录(这是一个词吗?)...似乎喜欢它应该很简单,我已经浏览了 MDN 和其他教程上的示例,但无济于事。

我的代码如下。我确定我做错了什么,但任何帮助/见解都将非常感激!

$(".vidlinks a").on('click', function(e) 
    var frsrc = 'https://player.vimeo.com'+$(this).attr('data-iframe')+'?title=0&byline=0&portrait=0&badge=0&autopause=0&player_id=0&autoplay=1',
        targetUrl = $(this).attr('href'),
        pgtitle = $(this).attr('title'),
        obj = url:targetUrl,ttl:pgtitle;
        $("iframe").attr('src', frsrc );
        $(".vidtitle h1").fadeOut("fast", function() 
            $(this).text(pgtitle);
        );
        $(".vidtitle h1").fadeIn("fast");

        window.history.pushState(obj, document.title, targetUrl);
        return false;
    );

   window.onpopstate = function(e) 
        $(".vidtitle h1").fadeOut("fast", function() 
            $(this).text(e.state.ttl);
        );
        $(".vidtitle h1").fadeIn("fast");
   

编辑:我也尝试使用 replaceState() 代替 pushState()。这种解决了双重输入问题,但使用后退按钮不会更改使用此方法的浏览器中的状态。这已经在 Chrome、Safari 和 FF 上进行了测试。

编辑编辑:奇怪的是,如果我完全注释掉 pushState() 语句,然后单击后退按钮,iframe 将重新加载到上一个视频,但没有其他任何变化。


3(编辑):这是 iframe 代码...

<iframe src="https://player.vimeo.com/video/VIDEOID?title=0&amp;byline=0&amp;portrait=0&amp;badge=0&amp;autopause=0&amp;player_id=0&amp;autoplay=1"   frameborder="0" title="THETITLE" webkitallowfullscreen="" mozallowfullscreen="" allowfullscreen=""></iframe>

VIDEOIDTHETITLE 只是最初从 php 传入的字符串。

这次我运行了一个console.log,这就是它的作用。我单击将新 iframe src 传递给 iframe 的链接(一次),但这会创建两个历史记录条目。第一次单击后退按钮时,iframe 会重新加载到上一个视频并且没有弹出状态。第二次单击“返回”时,我得到了包含所有属性的弹出状态。

【问题讨论】:

你用e.preventDefault()试过了吗..return false做的差不多,但值得一问 是的。这是我做的第一件事,然后改成return false 您的代码似乎对我有用。您能否在window.history.pushState 下放置debuggerconsole.log 以确认每次点击只调用一次推送。如果可能的话,您能否将大部分代码与 html 一起发布。 @Spartacus,你能添加你正在使用的 html 吗?或者如果可能的话 - 添加一个完整的工作 jsfiddle 来演示问题。 可能与 DOM 或鼠标有关! 【参考方案1】:

我相信我遇到了相同或非常相似的问题。使用 history.pushState() 后,必须单击两次后退按钮才能发生任何事情。我使用的是 iFrame。

解决方案是不分配给 iFrame.src,而是使用 'location.replace()' 代替:

   // BAD: iFrame.src   = href;

   iFrame.contentDocument.location.replace (href);    // GOOD

通常 location.replace() 无论是否与 iFrame 一起使用都不会创建历史条目。

我花了很长时间才弄清楚这个修复,因为我认为问题可能是由于我对 history.pushState() 的错误使用造成的。

所以请注意,我的问题不是 history.pushState() “创建两个条目”。它只创造了一个。问题是我还分配给 iFrame.src,它创建了第二个条目。

【讨论】:

【参考方案2】:

更改 iframe 的 src 会添加两个 pushState。技巧/黑客/解决方法是删除当前的 iframe,构建一个新的 iframe 片段并插入它。然后,调用你的 pushState。

来源: Updating an iframe, history and URL. Then making it work with back button

【讨论】:

就是这样......该死的,我正在拔头发,以为我编程出了问题。谢谢! 是的,第一句话;救生员。删除 iframe 可以停止我遇到的与此相关的双重状态问题!

以上是关于历史 API pushState() 创建两个条目的主要内容,如果未能解决你的问题,请参考以下文章

H5,API的pushState(),replaceState()和popstate()用法

window.history 方法总结

HTML5历史状态管理history API-pushState/replaceState与popstate事件

HTML5历史状态管理history API-pushState/replaceState与popstate事件

前端路由的实现 —— History的pushState和replaceState用法

需要点击两次才能回到历史(使用pushState)