不采用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  Zach Leatherman

    所有主流支持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值,无法将页面地址存入书签;

 

例子:

 

  • 测试页
  • 下载(2 HTML 文件, jQuery 1.2.6 和 dimensions)

     

    更新:需要时间做更多严格测试,目前还不支持Safari 。。。

  •  

     

    posted @ 2009-10-27 23:38  sparks345  阅读(1859)  评论(1编辑  收藏  举报