局部刷新之姿势研究

前言

今天晚上去跑操场跑累了,而且今天看书看的有点多,得消化一下。因此今天暂停一下设计模式的学习,学点姿势换换口味。 这个研究开头其实是前几天群里某个好奇心很严重的小伙伴看了我的博客问我,你的博客的不跳转刷新是怎么做到的?因为我博客是直接套用别人的模板。之前也没怎么看源码,我就丢锅:你自己看看咯。后来他甩给我两个词:pushState和replaceState就没下文了。我看到这两个属性好像没见过,但是看起来很有意思的样子就放到了调剂的项目列表中,今天正好队列轮到它=-=

pushState和replaceState

讨论话题之前我先看了下博客刷新的效果,当我点击不同页面的时候,左边两侧的内容是不动的,而且active效果还保留着,只有最右侧的内容改变了,而且url地址也改变了。如果是自己用js写我想应该没人想去尝试这种复杂的效果。

回归正题,因为有了关键词,我们先去MDN去看下介绍:

HTML5引进了history.pushState()方法和history.replaceState()方法,它们允许你逐条地添加和修改历史记录条目。这些方法可以协同window.onpopstate事件一起工作。

pushState()有三个参数:一个状态对象、一个标题(现在会被忽略),一个可选的URL地址。下面来单独考察这三个参数的细节:

状态对象(state object) — 一个JavaScript对象,与用pushState()方法创建的新历史记录条目关联。无论何时用户导航到新创建的状态,popstate事件都会被触发,并且事件对象的state属性都包含历史记录条目的状态对象的拷贝。


标题(title) — FireFox浏览器目前会忽略该参数,虽然以后可能会用上。考虑到未来可能会对该方法进行修改,传一个空字符串会比较安全。或者,你也可以传入一个简短的标题,标明将要进入的状态。

地址(URL) — 新的历史记录条目的地址。浏览器不会在调用pushState()方法后加载该地址,但之后,可能会试图加载,例如用户重启浏览器。新的URL不一定是绝对路径;如果是相对路径,它将以当前URL为基准;传入的URL与当前URL应该是同源的,否则,pushState()会抛出异常。该参数是可选的;不指定的话则为文档当前URL。


某种意义上,调用pushState()有点类似于设置window.location=’#foo’,它们都会在当前文档内创建和激活新的历史记录条目。但pushState()有自己的优势:

新的URL可以是任意的同源URL,与此相反,使用window.location方法时,只有仅修改 hash 才能保证停留在相同的document中。
根据个人需要来决定是否修改URL。相反,设置window.location='#foo',只有在当前hash值不是foo时才创建一条新历史记录。
你可以在新的历史记录条目中添加抽象数据。如果使用基于hash的方法,你只能把相关数据转码成一个很短的字符串。

对于replaceState()方法

history.replaceState()操作类似于history.pushState(),不同之处在于replaceState()方法会修改当前历史记录条目而并非创建新的条目。

当你为了响应用户的某些操作,而要更新当前历史记录条目的状态对象或URL时,使用replaceState()方法会特别合适。

两个说明看上去并不能解释我们的问题,因此直接祭出武器,chrome审查元素。经过查找,发现是引用了pjax。

Pjax

pjax是对ajax + pushState的封装,让你可以很方便的使用pushState技术。

同时支持了缓存和本地存储,下次访问的时候直接读取本地数据,无需在次访问。

并且展现方式支持动画技术,可以使用系统自带的动画方式,也可以自定义动画展现方式。

为了保险起见,去github拖官网的源码下来。然后当我看到源码第一句 Copyright 2012 我的内心是奔溃的=-=

然后我发现从官网脱下来的居然不能用。

后来看了chrome错误提示,放到服务器环境下,但是还是不能用!

尝试了很久发现还是无法使用,于是转换思想,找到了History

history

在github上,找到了jquery.history

将其修改了一下。

来看下效果。

imgn

html:

  <div id="ajax-links">
    <ul>
      <li><a href="http://192.168.2.115:8888/plugin/samples/ajax/1.html">load 1.html</a></li>
      <li><a href="http://192.168.2.115:8888/plugin/samples/ajax/2.html">load 2.html</a></li>
      <li><a href="http://192.168.2.115:8888/plugin/samples/ajax/3.html">load 2333.html</a></li>
    </ul>
    <div id="content"></div>
    <hr />
  </div>
  
js:

jQuery(document).ready(function($) {
	function load(num) {
	  $('#content').load(num);
	}
	
	$.history.init(function(url) {
	      load(url == "" ? "1" : url);
	  });
	
	$('#ajax-links a').live('click', function(e) {
	      var url = $(this).attr('href');
	      console.log(url);
	      url = url.replace(/^.*#/, '');
	      $.history.load(url);
	      return false;
	  });
});


对于插件源码 做如下修改:

  //原来是对Url处理 但是为了直接在浏览器显示完整的url 去掉this.encoder(hash)

  (win || window).location.hash = hash;

但这个刷新并不是完全我想要的。不过今天先到这里。遗留的问题以后再解决。

Table of Contents