藏井阁

" Scientists ask why, engineers ask why not? "

hashchange Event – 监测URL的hash变化

通过URL传值,在?后附加以=连接的键值对,各键值对间以&连接;也可以通过URL传递页面参数,在”#”后附加的方式。两者最大的一个区别在于:后者不会发起请求,不会导致页面刷新。常见应用场景在于:不需要请求服务器,由浏览器端脚本直接定位到某个条件下的页面展示。例如:在这个页面中http://www.istartedsomething.com/bingimages/#20101106-us,带hash值打开的是展示某个大图的页面,不带hash值打开(http://www.istartedsomething.com/bingimages/)的只是一个日历的图片集界面,需要再次点击才能展示某个大图。

如果需要根据URL的hash值变化,来进行不同的页面处理,需要一个监测方案。最常见的方法就是通过一个定时程序,不停的去检测url中hash的变化,一旦检测到变化,则触发操作。

但这个方案并不是实时触发的,而且究竟该多久检测一次,没有一个有依据的数值。如果数值过大,可能会影响到页面的快速呈现;如果数值过小,则会引起过高的资源占用。

比较完美的一个方式是采用onhashchange的事件监测。

hashchange事件在html5中有定义,在url的hash段变化的时候触发。目前支持onhashchange的浏览器有:

秉承不应基于浏览器检测,而应基于对象和方法检测的原则,可用 if(‘onhashchange’ in window) { } 检测浏览器是否支持onhashchange。这里不能用 typeof window.onhashchange === ‘undefined’ 来检测,因为很多支持onhashchange的浏览器下,其初始值就是undefined。

需要注意的是,在IE8以ie7的模式运行时,window下存在onhashchange这个方法,但是永远不会触发这个事件,因此需要先检测IE的document.documentMode

综上所述,采取比较完善方式的代码片段:

    if( ('onhashchange' in window) && ((typeof document.documentMode==='undefined') || document.documentMode==8)) {
        // 浏览器支持onhashchange事件
        window.onhashchange = hashChangeFire;  // TODO,对应新的hash执行的操作函数
    } else {
        // 不支持则用定时器检测的办法
        setInterval(function() {
            var ischanged = isHashChanged();  // TODO,检测hash值或其中某一段是否更改的函数       
            if(ischanged) {
                hashChangeFire();  // TODO,对应新的hash执行的操作函数
            }           
        }, 150);
    }

通过URL hash来传递数据,在某些场景下相对URL query的方式,不会引发浏览器发起新连接,是一个很好的优化。同时可让页面中的某些中间交互环节通过URL可访问到,是一个很好的体验。试试吧:)

类别: Web开发

Tags: hashchange event,html5,javascript,onhashchange

damon pang

大魔

Damo

i#impng.com

专注Web开发,爱电影,爱One Piece.