Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
343 views
in Technique[技术] by (71.8m points)

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

I’ve made a one page site. When user clicks on the menu buttons, content is loaded with ajax. It works fine. In order to improve SEO and to allow user to copy / past URL of different content, i use

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

It works fine. URL changes and the browser doesn’t reload the page

However, when user clicks on back button in browser, the url changes and the content have to be loaded.

I've done this and it works :

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

Do you know if there is a way to improve this code ?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

What I did was passing an object literal to pushState() on page load. This way you can always go back to your first created pushState. In my case I had to push twice before I could go back. Pushing a state on page load helped me out.

HTML5 allows you to use data-attributes so for your triggers you can use those to bind HTML data.

I use a try catch because I didn't had time to find a polyfill for older browsers. You might want to check Modernizr if this is needed in your case.

PAGELOAD

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

EVENT HANDLERS

An object filled with default information

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

Bind the history.pushState() trigger. In my case a delegate since I have dynamic elements on the page.

// 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);
    }
});

Bind the history.back() event to a custom button, link or something. I used .preventDefault() since my button is a link.

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

When history pops back -> check for a pushed state unless it was the first attempt

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

Using object literals as a parameter is handy to pass your id's. Then you can use one function showContent(id).

Wherever I've used this it's nothing more than a jQuery object/function, stored inside an IIFE.

Please note I put these scripts together from my implementation combined with some ideas from your initial request. So hopefully this gives you some new ideas ;)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...