单页面时代 - Ajax应用可以改变用户的 URL 地址栏并且支持后退按钮

详细内容参看 : http://codecampo.com/topics/84

CodeCampo 是一个小型开发者社区,其代码开源托管于 Github,作者 @chloerei,订阅 @codecampo

本人做了归纳与调整。


一、有两个问题需要克服
1. Javascript 有一个函数可以改变当前 URL 路径,并载入页面。
      window.location = '/'

而如果只改变 URL 的 # 号后面部分,不会导致浏览器重新载入网页。
      window.location = '#here'    //不会导致页面刷新

2. 浏览器不懂得记录 Ajax 调用的状态。

3. 从非 Ajax 页面返回到 Ajax 页面。处理所有的细节的话,这问题比较棘手存。
           采访的方法,让其不存在此情况 : 采用若打开非ajax页面,target="_blank"

二、目标
理想中应该让 Ajax 调用达到这样的状态:
如果 Ajax 调用后的页面逻辑上已经跟之前不是同一个页面,那么 URL 应该随之改变。
前提同上,那么在新页面点击浏览器的后退按钮,应该回到 Ajax 调用前的页面。


三、方案
1. 只改变 URL Hash 的单页面应用 , 对主流浏览器的支持程度很高。
现在的 Twitter,Google,Facebook 的 URL 地址充斥着 #号或者 #! 号。例如一个新版 Twitter 地址是这样的
https://twitter.com/#!/chloerei
    其原理:#号后面的改变不会导致页面加载
步骤:
step1: 有关 Ajax 调用的链接全部用 #path 作为链接目标
step2: 设置 onhashchange 事件 (窗口 window 对象的 hash 值(# 号后面部分)发生变化时,会调用 onhashchange 事件。)
在此事件里面,调用ajax方法。如:
window.onhashchange = function(){ ajax方法 }

此方案的副作用 : 
把路径写在了 Hash 里面破坏了 URL 原先的含义。

2. 基于 history.pushState API   只支持对HTML5 友好的浏览器
  步骤:
           step1: 在发送 ajax 请求之前把目标地址推进浏览器的历史记录.  (HTML5 新增了 history.pushState 方法,用以向浏览器添加历史记录,但是不触发页面载入)
if (history && history.pushState) {
history.pushState(null, document.title, this.href);
}

 step2: 处理后退按钮.  浏览器后退的时候会触发 onpopstate 事件,所以要给这个事件挂上处理方法。
if (history && history.pushState) {
$(window).bind("popstate", function() {
$.getScript(location.href);
});
}

step3: 从非 Ajax 页面返回到 Ajax 页面   (也可以不需要step3,采用若打开非ajax页面,target="_blank")
这时候要做两个处理:
1)要求 Ajax 相关页面不缓存    (缺点:牵扯到性能)
2)处理 popstate 的方法增加一个标志位,第一次载入页面的时候不要调用后面的逻辑。
if (history && history.pushState) {
var loaded = false;
$(window).bind("popstate", function() {
if (!loaded) {
loaded = true;
} else {
$.getScript(location.href);
}
});
 }
   3. 综合以上两种方案 :
  若浏览器有支持history.pushState,则采用方案2 ,否则采用方案1 。 代码实现如下

step1: 在发送 ajax 请求之前 . 设置两种不同写法的url
if (history && history.pushState){
history.pushState(null, document.title, this.href);
}else{      // 不支持 history.pushState
// #path 作为链接目标
window.location = "#!path";
}
step2: 处理回退按钮

if (history && history.pushState){
var loaded = false;
$(window).bind("popstate", function() {
if (!loaded) {
loaded = true;
} else {
$.getScript(location.href);
}
});
}else {            // 不支持 history.pushState
window.onhashchange = function(){ ajax方法 }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值