通过iframe实现页面的局部刷新
一个网站是由许许多多页面组成的,超链接将这些页面连接起来,给了用户一个完整的使用体验。用户通过超链接打开一个页面时,浏览器会回收当前页面然后再渲染新页面。有时候我们并不希望是这样,比如对于一个音乐网站,我们不希望用户在切换页面时中断当前歌曲的播放。这就需要做到页面的刷新是局部而不是全部。目前大概有两种方法可以实现这种功能。一是将整个网站做成只有一个页面,模块切换完全靠客户端的js实现;二是通过嵌套iframe的方式实现。iframe方式虽然传统,但是和单页面应用相比也有许多优势。比如:内存一般不会泄漏,seo很方便等。本文将主要介绍iframe的实现方式。
如上图,在最外层的页面嵌套一个iframe,通过改变iframe的src值来实现页面的切换。我们可以将站内所有链接的target值设为iframe。由于iframe是一个独立的浏览器窗口,其切换并不会刷新其外层的容器,这样就实现了页面局部刷新的效果。效果是达到了,不过还存在一个问题,那就是页面的URL不能体现在浏览器的地址栏里,这样的用户体验是非常差的。浏览器的地址栏表示的是最外层页面的地址,如果改变这个地址就会造成整个页面的刷新。不过好在浏览器为URL增加了hash部分。hash并不是http协议的内容,只是在客户端使用的,hash的改变不会刷新页面。所以在外层,可以用hash来体现iframe页面的地址。比如iframe的地址为http://a.b.com/user?id=123 ,那么转换到浏览器地址栏可能是http://a.b.com/#/user?id=123。 通过简单的改动就能实现此功能。
上面的流程图反映了一次页面跳转的过程。在iframe中,需要实现一个全局的点击事件代理,将所有链接的点击事件拦截下来。拦截后,将链接href值转换成hash地址,并修改外层src值。外层src值改变后,会触发hashchange事件,在该事件处理函数中将hash地址再次转换成页面真实地址并刷新iframe。这里有个细节需要注意,刷新iframe时,不能直接设置src值或者location.href的值,因为这会使得iframe也相应产生一条历史记录,这回导致浏览器的前进后退需要点两次才生效。通过调用location.replace()方法可以避免iframe产生历史记录。不过该方法在ie10+浏览器下有个严重的bug。使用浏览器的前进和后退键时会导致所有页面的刷新,这就破坏了局部刷新的需求了。这应该是浏览器实现上的一个bug,没有办法直接解决,不过可以用其他方法绕过去。避免iframe产生历史记录的方法还有一种,就是在刷新iframe时,先要将原来的iframe节点删除,然后创建一个新的iframe节点,并将其src设为对应地址。此时iframe的刷新就不会产生多余的历史记录了。
可以看到内嵌iframe的方式实现是比较简单的,关键的一点就是要把浏览器的历史记录问题处理好。希望本文提供的信息能有所帮助。