为 AJAX 加载的内容操作浏览器历史记录

Posted

技术标签:

【中文标题】为 AJAX 加载的内容操作浏览器历史记录【英文标题】:Manipulating Browser History for AJAX loaded content 【发布时间】:2017-09-20 15:43:46 【问题描述】:

我有一个页面,左侧是导航链接,右侧是内容 div。导航链接 html 是这样设置的。

<a href="javascript:;" class="nav-link" data-mode="myModeValue">Test</a>

我已经设置了一个如下所示的 JavaScript 函数,我认为它会绑定到链接,将新状态推送到浏览器历史记录中,并根据数据模式值加载该链接的内容。 Going FORWARD 效果很好,但是当我后退时,有时我必须单击两次才能返回到上一个哈希,我不知道为什么。

这是我目前所拥有的。

<script language="javascript">
    // Create var indicating the CURRENT mode we're on - home being the default when page loads
    currentMode = "home"; 
    // Push the default page (mode) into the history
    history.pushState(null, document.title, location.pathname + "#!/detail-mode/" + currentMode);

    // bind to my nav links
    $(document).on('click', '.nav-link', function(e)
        e.preventDefault();
        ajaxLoadVehicleSearchDetailContent($(this).data('mode'));
    );

    function ajaxLoadVehicleSearchDetailContent(mode) 
        // Get the mode and link object
        var thisMode = mode.toString().toLowerCase();
        var thisLink = $('a[data-mode="' + mode + '"]');
        // If we're switching to a different tab - continue
        if (currentMode != thisMode) 
            currentMode = thisMode;     
            // Get the content via AJAX
            $.ajax(
                url: "/myAjaxFunctionFileURL",
                type: "POST",
                data:  method:"getTabContent", mode:thisMode ,
                success: function(result) 
                    history.pushState(null, document.title, location.pathname + "#!/detail-mode/" + thisMode);
                    // Update the content area - fadeOut,replace,fadeIn
                    $('#contentArea').fadeOut(globalAnimationDuration, function() 
                        $('#contentArea').html(result).fadeIn(globalAnimationDuration);
                        $('.nav-link').removeClass('current');  
                        thisLink.addClass('current');                   
                    );
                
            );     
        
    

    // Listen for the popstate and load correct content when user goes BACK in history
    window.addEventListener("popstate", function() 
        if (location.hash.indexOf("#!") != -1) 
            var thisMode = location.hash.split("/").slice(-1)[0];           
            ajaxLoadVehicleSearchDetailContent(thisMode);           
        
    , false);
</script>

globalAnimationDuration var 只是一个值为 500 的变量。

有人能解释一下为什么回去时会出现奇怪的行为吗?或者甚至是一个很好的例子来展示如何执行我可以遵循的任务并相应地更新我的方法?

JSFiddle Here

谢谢!

【问题讨论】:

盲目猜测:如果您在按钮上单击两次太快,会触发两个请求,因此推送状态发生了两次?你应该console.log你所有的pushstate,看看是否会发生这种情况。如果是这样,只需禁用您的后退/前进按钮,直到进程结束(无论 ajaxRequest 成功或失败!) 想通了。这是我的逻辑错误。在下面回答。 【参考方案1】:

我想通了。由于我在前进和后退导航中都调用了相同的ajaxLoadVehicleSearchDetailContent,因此单击后退时它错误地将项目添加到堆栈中。所以它会从堆栈中弹出项目,调用函数,然后将其重新添加到堆栈中,除非它是当前选项卡。

我的解决方案向我的ajaxLoadVehicleSearchDetailContent() 方法添加了一个附加参数,如下所示。

function ajaxLoadVehicleSearchDetailContent(mode,backward) 
        // Get the mode and link object
        var thisMode = mode.toString().toLowerCase();
        var thisLink = $('a[data-mode="' + mode + '"]');
        // If we're switching to a different tab - continue
        if (currentMode != thisMode) 
            currentMode = thisMode;     
            // Get the content via AJAX
            $.ajax(
                url: "/myAjaxFunctionFileURL",
                type: "POST",
                data:  method:"getTabContent", mode:thisMode ,
                success: function(result) 
                    if (!backward) history.pushState(null, document.title, location.pathname + "#!/detail-mode/" + thisMode);
                    // Update the content area - fadeOut,replace,fadeIn
                    $('#contentArea').fadeOut(globalAnimationDuration, function() 
                        $('#contentArea').html(result).fadeIn(globalAnimationDuration);
                        $('.nav-link').removeClass('current');  
                        thisLink.addClass('current');                   
                    );
                
            );     
        
    

然后,当我从导航链接调用它时 - 发送 false,当我从 popstate 事件调用它时,我调用它为 true。

【讨论】:

以上是关于为 AJAX 加载的内容操作浏览器历史记录的主要内容,如果未能解决你的问题,请参考以下文章

chrome退出清除历史记录

页面缓存的操作(搜索历史记录),页面搜索功能实现

Django is_ajax 历史回溯

iOS 以编程方式删除浏览历史记录

如何在 iframe 之外操作历史记录

奇怪和疯狂的 PHP 错误,清除浏览器历史记录后的页面加载导致脚本多次运行 [重复]