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~~