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的浏览器有:
- Gecko 1.9.2 (Firefox 3.6/Thunderbird 3.1/Fennec 1.0)
- IE 8
- WebKit 528+ (Safari/Google Chrome)
- Opera 10.70
秉承不应基于浏览器检测,而应基于对象和方法检测的原则,可用 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可访问到,是一个很好的体验。试试吧:)