如何在使用HTML5 pushState更改浏览器URL时处理后退按钮

How to handle back button while changing the browser-URL with HTML5 pushState

本文关键字:URL 浏览器 处理 按钮 pushState HTML5      更新时间:2023-09-26

我制作了一个单页网站。当用户单击菜单按钮时,内容将使用ajax加载。它运行良好。为了改进SEO并允许用户复制/过去不同内容的URL,我使用

function show_content() {
        // change URL in browser bar)
        window.history.pushState("", "Content", "/content.php");
        // ajax
        $content.load("ajax/content.php?id="+id);
}

它运行良好。URL更改,浏览器不会重新加载页面

然而,当用户点击浏览器中的后退按钮时,url会发生变化,必须加载内容。

我已经这样做了,它起作用:

 window.onpopstate = function(event) {
        if (document.location.pathname == '/4-content.php') {
            show_content_1();
        }
        else if (document.location.pathname == '/1-content.php') {
            show_content_2();
        }
        else if (document.location.pathname == '/6-content.php') {
            show_content_();
        }
    };

你知道是否有改进代码的方法吗?

我所做的是在页面加载时将对象文字传递给pushState()。通过这种方式,您可以始终返回到第一个创建的pushState。就我而言,我得推两下才能回去。在页面加载上推送状态帮助了我。

HTML5允许您使用数据属性,因此对于触发器,您可以使用这些属性绑定HTML数据。

我使用try-catch是因为我没有时间为旧浏览器找到polyfill。如果您的情况需要,您可能需要查看Modernizr。

页面加载

try {
    window.history.pushState({
        url: '',
        id: this.content.data("id"), // html data-id
        label: this.content.data("label") // html data-label
    }, "just content or your label variable", window.location.href);
} catch (e) {
    console.log(e);
}

事件处理程序

一个填充了默认信息的对象

var obj = {
    url: settings.assetsPath, // this came from php
    lang: settings.language, // this came from php
    historyData: {}
};

绑定history.pushState()触发器。在我的情况下是一个委托,因为我在页面上有动态元素。

// click a trigger -> push state
this.root.on("click", ".cssSelector", function (ev) {
    var path = [],
        urlChunk = document.location.pathname; // to follow your example
    // some data-attributes you need? like id or label
    // override obj.historyData
    obj.historyData.id = $(ev.currentTarget).data("id");
    // create a relative path for security reasons
    path.push("..", obj.lang, label, urlChunk);
    path = path.join("/");
    // attempt to push a state
    try {
        window.history.pushState(obj.historyData, label, path);
        this.back.fadeIn();
        this.showContent(obj.historyData.id);
    } catch (e) {
        console.log(e);
    }
});

history.back()事件绑定到自定义按钮、链接或其他内容。我使用了.preventDefault(),因为我的按钮是一个链接。

// click back arrow -> history
this.back.on("click", function (ev) {
    ev.preventDefault();
    window.history.back();
});

当历史弹出时->检查推送状态,除非是第一次尝试

$(window).on("popstate", function (ev) {
    var originalState = ev.originalEvent.state || obj.historyData;
    if (!originalState) {
        // no history, hide the back button or something
        this.back.fadeOut();
        return;
    } else {
        // do something
        this.showContent(obj.historyData.id);
    }
});

使用对象文字作为参数可以方便地传递id。然后您可以使用一个函数showContent(id)

无论我在哪里使用this,它只不过是一个jQuery对象/函数,存储在IIFE中。

请注意,我将我的实现中的这些脚本与您最初请求中的一些想法结合在一起。所以希望这能给你一些新的想法;)