嘿, 我是Mofei!
Seamless Refresh with onhashchange and AJAX

Recently, I've been busy with revamping a cloud storage project, changing from the previous method of clicking directories to jump to the next page, to implementing a seamless refresh functionality directly using AJAX. Considering that users might share the current destination's address with friends, I opted for the hash in HTML5's history API since handling HTML5 compatibility can be quite cumbersome. Although hashchange does not support IE6 and IE7, the good thing is that IE can recognize hashes, making compatibility a bit easier.

onhashchange is primarily aimed at addressing the issue of the browser's "back" button being ineffective due to AJAX seamless interactions; it is still considered a relatively new method. When JS interacts by changing the hash, for instance, a.html#page=1, the ‘#page=1’ here is the hash. Changing the hash via JS does not trigger the load event, so when you click the "back" button, you will notice that other than the hash changing, nothing else has changed. Hence, this is where the onhashchange method comes into play; when the user clicks "back", it captures the changed hash and performs the corresponding operations.

First, let's look at compatibility:

Internet Explorer 8+

Firefox 3.6+

Chrome 5+

Safari 5+

Opera 10.6+

Basically, there are no major issues except for IE6 and 7, so here’s the method.

        (function() {
    if ('onhashchange' in window) {
        //if browser support onhaschange  如果浏览器支持onhaschange事件
        if (window.addEventListener) {
            window.addHashChange = function(func, before) {
                window.addEventListener('hashchange', func, before);
            };
            window.removeHashChange = function(func) {
                window.removeEventListener('hashchange', func);
            };
            return;
        } else if (window.attachEvent) {
            window.addHashChange = function(func) {
                window.attachEvent('onhashchange', func);
            };
            window.removeHashChange = function(func) {
                window.detachEvent('onhashchange', func);
            };
            return;
        }
    }
    //if the browser not support onhaschange 如果不支持的话
    var hashChangeFuncs = [];
    var oldHref = location.href;
    window.addHashChange = function(func, before) {
        if ( typeof func === 'function')
            hashChangeFuncs[before ? 'unshift': 'push' ](func);
    };
    window.removeHashChange = function(func) {
        for (var i = hashChangeFuncs.length - 1; i >= 0; i--)
            if (hashChangeFuncs[i] === func)
                hashChangeFuncs.splice(i, 1);
    };
    //!!important!! 用setInterval检测has的改变
    setInterval(function() {
        var newHref = location.href;
        if (oldHref !== newHref) {
            oldHref = newHref;
            for (var i = 0; i < hashChangeFuncs.length; i++) {
                hashChangeFuncs[i].call(window, {
                    'type' : 'hashchange',
                    'newURL' : newHref,
                    'oldURL' : oldHref
                });
            }
        }
    }, 100);
})();
// Usage, infinitely many times: 使用方法
addHashChange(function(e) {
    alert(e.newURL || location.href);
});

If the native event is supported, the native event is called; if not, setInterval is used for detection. There seems to be a method that does not require setInterval, which I intended to look up, but Google has recently been severely blocked by the GFW, and Baidu isn't helping, so I couldn't find detailed methods. If you find something, don't forget to share it below~~

THE END

More Articles You Might Be Interested In

I had so many questions while writing this—what’s your take?

avatar

Mofei's Friend (Click to edit)

What's on your mind today?

HI. I AM MOFEI!

NICE TO MEET YOU!