【问题标题】:How to handle back button while changing the browser-URL with HTML5 pushState如何在使用 HTML5 pushState 更改浏览器 URL 时处理后退按钮
【发布时间】:2013-12-08 01:06:37
【问题描述】:

我制作了一个单页网站。当用户单击菜单按钮时,将使用 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 发生变化,浏览器不会重新加载页面

但是,当用户点击浏览器中的后退按钮时,网址会发生变化,并且必须加载内容。

我已经这样做了,它有效:

 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_();
        }
    };

你知道有没有办法改进这段代码?

【问题讨论】:

    标签: javascript ajax html browser-history pushstate


    【解决方案1】:

    我所做的是在页面加载时将对象文字传递给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,它都只不过是一个存储在IIFE 中的jQuery 对象/函数。

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

    【讨论】:

    • 感谢您的详细解释。将对象文字传递给 pushState() 是更好的解决方案。
    猜你喜欢
    • 2013-01-10
    • 2023-02-23
    • 2015-08-12
    • 2014-12-22
    • 2018-06-02
    • 1970-01-01
    • 2013-03-19
    • 1970-01-01
    • 2012-12-19
    相关资源
    最近更新 更多