某天上班,偶然打开网页版的喜马拉雅,随手点了首推荐音频。。。于是伴随着动词大词,动词大词,继续逛着它的首页。
  一个不小心,又点进了老郭的相声,哎,还是木有更新,不过老段子也可以再听听,正当老夫要点播的时候,突然!哎呀!卧槽!卧槽!牛逼啊!我都逛了这么多页面了,耳机里的”动词大词”竟然连顿都没打,当时还打开了一下本地播放器,以为是它播放的音乐。
  详细情形是这样的:我在喜马拉雅的a页面播放了音乐,然后又去b页面c页面,音乐却并没有卡顿现象,稳如死狗!注意,这里说的是连卡顿都没有,不是说跳到别的页面会继续播放。
  国内的在线音乐平台有很多,实现喜马拉雅的这种哥还是头一回见啊。大部分都是采取的本地缓存音乐进度,跳到别的页面再读取进度,继续播放,但切页面的时候肯定是会有卡顿的。所以这里给喜马拉雅的用户体验32个赞!
  那么问题来了,这种网页播放器是如何实现的?

  简单点说,其实就是使用了html5的api:history.pushstate

  1. 页面中,所有的a标签,js对其做了点击事件的拦截,如果是支持该API的浏览器不会发生跳转,而是通过ajax请求该链接,返回结果是一串类似于如下的json:
1
2
3
4
{
"html":"<div class='xxx'>xxx</div>",
"title":"页面标题"
}
  1. 通过js将html里的内容插入到页面的指定容器中去
  2. 使用histoyr.pushstate,强势插入一条浏览历史
      于是当前浏览器的页面内容会被更新,访问地址会变成该a标签的链接,页面标题变成返回结果中的title。所以看起来就会和跳转页面一样,但实际上页面并未发生过任何跳转,至始至终都是在一个页面中进行各种ajax请求而已,所以歌曲的播放当然不会卡顿了。
      好了,揭秘完毕!小伙伴们是不是也可以使用上述步骤来创建自己的单页应用了呢?别急,待我先喷一喷这种单页应用的缺点先!
  • 需要后端配合渲染页面。区分ajax请求和浏览器请求,即如果是ajax请求页面,则返回上述json,否则正常返回整个页面内容以供跳转。
  • 需要js/css路由(某些框架就可以实现)或初次载入即加载完所有js/css,并解决冲突。
      因为ajax请求返回的仅仅是html部分,没有也不能够包含页面对应的js/css,一旦包含了,很可能就会形成全局变量冲突,事件冲突,样式混乱等问题,请求的页面越多,问题越严重!这对于前端的小伙伴来说真是日了狗了。。没法再轻松愉快的维护各自页面各自的静态资源了,写着a页面还得操着b页面的心,遵循一堆约定。而且本人也比较反感因为使用了某些框架(比如:react.js)就要放弃html各种纯天然的写法,毕竟原生态的,才是我们最熟悉的。
  • 感觉两条太少了,凑个数行不。。。

 
我知道,看到这里肯定有人想喷我了。时代在进步,现在前端各种mvc框架完全能够实现这种需求,为毛还嫌麻烦?我想说,每种框架都
有它的适用情景,也都有值得我们学习的地方,but!每个团队的开发模式,编程水平,项目时间都不同,适合自己的才是最好的。并且现代
浏览器的性能,人们的带宽都取得了长足的进步,有时候为了一点性能提升而要改变适合整个团队的编码习惯,是不是有点舍近求远了呢?

  而优点当然也有了,就1条!

  太特么省流量了。因为各个页面会有很多相同部分,ajax仅返回异同部分即可,所以页面的体验会更加流畅,并可以有效减少http请求。。好像不止1条,不管了。

  那么接着html原生写法的思路,有没有一种方式能够让我们不用管前后端配合,也不用鸟静态资源路由,就像做多页站点那样无痛创建单页应用呢?相信你脑海中已经出现那个古老科技了,对!就是iframe

  1. 用iframe将页面包起来
  2. 播放器给挪到外面去
        这样iframe中的页面爱咋跳咋跳,同样也不会影响到外面播放器的运行
  3. 使用html5的另一个API:history.replacestate改改浏览器地址,改改标题
  4. iframe的跳转又天然会插入一条浏览历史

简直完美!

  利用以上原理,鄙人写了一个插件—— singlePage.js(点我查看文档)
  帮助大家更自然地创建单页应用,没有那么多的屁事儿,你要做的仅仅只有一步,引入它!
  查看演示(仿喜马拉雅播放器)