不采用interval方式模仿onHashChange
前些天有一个类似的需求,网上找了很久基本上都是用定时器检测location.hash有没有变化,但总觉的这样做不太合适。无意间发现了一篇《Emulating onhashchange without setInterval》,大概翻一下,如果有类似需求的同学们可以参考下。
E文好的直接看这里: http://www.zachleat.com/web/2008/08/21/onhashchange-without-setinterval/
JS好的直接看这里:http://www.zachleat.com/Projects/history/
by
所有主流支持javascript的浏览器都有一个限制,当你改变 location.hash
的时候,你如何通知到浏览器,并让它把访问历史记录下来?当然,你可以在改变 location.hash 的时候主动的触发,但如果用户点击了 前进/后退 的按钮的情况下呢?
YUI’s History component 和 Really Simple History 都采用了 setInterval 的方式,定时比较地址,当改变的时候触发。但这并不是最好解决方案,作为正统的前台工程师,我们应该尽可能的避免定时器的循环。IE8将支持onhashchange 事件 ,以便客户端可以捕获,这点自然很好,但是,确切的说,我们已经有了不需要用定时器的跨浏览器的结决方案。
不需要用定时器的跨浏览器的结决方案,具体实现如下:
1.页面初始化时,我们加载一个绝对定位的iframe到页面里,并将其位置设到 -500px, -500px,使用户无法看到。再框架页内,我们用兼容写法添加 onscroll 事件,并使其能够获取到滚动到的位置。我的例子中是由jQuery和dimensions插件来完成的,用其他的库或者直接写也很容易实现的;
2.为了让浏览器记录下hash改变的历史,我们首先要将一个 <a name="hashString">hashString</a>
节点添加到iframe的body节点中,并设置a的css样式,使其比例增大到与iframe的高度,保证切换锚点时会触发onscroll事件;
3.然后,我们改变iframe的hash,指向相应的a锚点,iframe会滚动到对应的内容,同时浏览器也会在历史记录中记下相应的记录。
4.同时,iframe页内,也会触发之前准备好的onscroll事件(IE下有个特例,浏览器已经记录历史,但是读取hash值的时候发现并没有改变,相应的,我们可以比较<a>与scrollY/pageOffsetY属性的方式来代替);
这种方法有个好处,你再也不需要自己维护历史了,它将很多繁杂的工作都替你做了,它甚至可以维护页面上其他iframe的历史。
优点:
- 支持后退,可以作为纯AJAX页面的历史管理器;
- 页面体积小,测试页和iframe共计2.67K,其中已包括了dimensions,和实现了所有功能的脚本;
- 跨浏览器,支持 FF3, IE7, IE6, Opera 9.5, (暂不支持Safari下面说明);
局限:
- 不支持书签功能,我们并没有改变顶层页面的hash值,无法将页面地址存入书签;
例子:
更新:需要时间做更多严格测试,目前还不支持Safari 。。。