[翻译]175 AJAX浏览记录和书签

175: AJAX浏览记录和书签观看原视频

查看英文原版

上一集我们给产品列表的分页加上了AJAX功能。与通常的HTML链接不同,通过非侵入式的JavaScript在分页链接上绑定click事件,他们就可以在点击时发出AJAX请求,从而将页面中的主体部分替换为一页新的产品内容。

 

 

AJAX带来的问题

因为我们使用了AJAX来更新页面,所以当新的一页产品被加载时URL不会发生改变。这就意味着,当我们刷新整个页面、或者收录书签后再打开那一页的话,不管之前我们在哪一页,都只会显示第一页的产品。另外一个使用AJAX的后果是,翻页以后上一页并没有被记到浏览器的历史记录中,所以我们没法用返回、前进按钮在我们之前看过的页面中前后浏览。

 

这些是使用了AJAX方法的问题;那么我们有什么解决办法吗?这将是本集我要告诉你们的内容。要说明的是,因为我们要解决的问题主要是在客户端,所以本集会更多地讨论JavaScript、而不是Ruby on Rails。

有很多JavaScript程序库可以用来解决这个问题。在Google code上我们可以找到一个最早的叫reallysimplehistory的。Yahoo也有一个叫Browser History Manager的。Yahoo有很多JavaScript程序库,所以这个很值得一看。还有一个是Asual的SWFAddress,可以用于Flash、也可以用于JavaScript。

 

所有上面提到的这些程序库都是支持纯JavaScript代码,但是在我们的程序中使用了jQuery,所以最好能找到一个能支持它的。上面提到的Asual曾经发布过一个叫jQuery Address的插件,可以用。但是我们要用的是另外一个插件,叫jQuery URL Utils plugin。这个插件虽然小(压缩后不到4KB),但是功能很丰富,也有很好的文档。

 

我们先下载这个插件,在程序目录/public/javascripts下保存为jquery.ba-url.js,然后我们在产品index页面中引用它。因为需要在pagination.js之前引用它,所以我们需要修改引用JavaScript的那行代码,把它加到pagination的前面。

 

<% javascript 'jquery.ba-url', 'pagination' %>  

 

改进一下我们的分页代码

在我们开始修改代码来用这个插件之前,我们先看一下上集中我们写的分页的代码。

$(function () {     
  $('.pagination a').live("click", function () {       
    $('.pagination').html('Page is loading...');       
    $.get(this.href, null, null, 'script');       
    return false;     
  });   
}); 

 

我们可以对这个代码稍稍做些改进。不再使用$.get而是用$.getScript来发起AJAX请求,传入的参数是我们要调用的URL。

 

$.getScript(this.href);  

 $.getScript函数向作为参数传入的URL发起一个GET请求,然后执行返回的JavaScript代码,功能和$.get一样,但是代码更简洁。

 

为每一页指定一个唯一的URL

现在来给我们的程序实现一些新的功能。我们要做的是每当一个分页链接被点击后,用JavaScript来更新URL。这样每一个产品页都有一个唯一的URL,我们就可以把它加到书签里了。我们需要给我们所在产品页对应的唯一URL加上一个锚标签。例如,对于第二页,如果程序是在本地运行,URL将会表示为:

 

http://localhost:3000/#page=2

我们可以利用之前下载的插件来设置这个URL。插件有一个叫$.setFragment的方法,能够修改当前URL的锚标签部分。在我们的pagination代码中可以这样来用:

 

$(function () {     
  $('.pagination a').live("click", function () {       
    $.setFragment({ page: $.queryString(this.href).page });       
    $('.pagination').html('Page is loading...');       
    $.getScript(this.href);       
    return false;     
  });   
}); 

工作原理是这样的,给$.setFragment传入一个JavaScript的原值对象,它会把他们转成象querystring一样的键值对。我们希望得到一个形如page=x的锚标签,所以我们传入一个键是page的对象。但是我们如何得到页码值呢?其实,这个页码值已经在我们AJAX调用的URL的 querystring里面了。要得到这个值,我们可以用$.queryString函数把querystring中的键值对转化为JavaScript对象,然后从page项中就可以得到这个值。

 

我们现在可以试一下我们修改后的pagination代码。加载完我们的产品页面,然后点击“下一页”,随着AJAX请求的发出,URL也发生了变化。我们看到浏览器的返回按钮现在也是可用的,说明上一页已经被记录到浏览器的历史记录中了。

 

 

搞定返回按钮

事情还没有完。虽然返回和前进按钮可以用了,但是点击它们时并不能改变页面的内容。还有就是,当我们重新打开我们收录的书签页,或者刷新页面,那么,不管URL中锚标签的页码值是多少,显示的都是第一页的产品项。

 

我们先来解决返回和前进按钮。为了让它们能工作,我们需要侦听URL中锚标签变化时的一个事件。这是我们用的这个插件所支持的功能。在我们的pagination代码中增加下面一行JavaScript代码,可以激活这个功能。

 

$.fragmentChange(true); 

现在我们就可以侦听到这个事件了。我们可以调用$(document).bind函数,传入这个我们要侦听的事件的名字。如果我们再传入我们关注的那个锚标签的名字,那么这个事件就只会在那个锚标签发生改变时被触发。我们还需要传入一个绑定的函数,在事件被触发时能够被执行。现在,我们只是弹出一个alert来测试一下是不是万事俱备。

 

$(document).bind("fragmentChange.page", function () {     
  alert('fragment changed!');   
});  

现在我们刷新页面并且点其中的一个链接,我们可以看到弹出的alert,同时也看到URL中的锚标签也变化了。当我们点击返回或者前进按钮时,我们也可以看到alert弹出来。

 

 

现在点击任意一个链接都可以捕获到fragmentChange事件,我们就可以把AJAX请求搬到那个响应事件的函数中去了。那样的话,点击返回按钮也可以发出AJAX请求了。但是,这给我们带来了一点小问题。下面是我们要搬过去的那行代码。

 

$.getScript(this.href);  

 上面的代码中要引用的分页链接已经没法再得到了,我们不得不用其他方法得到页码值。所幸,点击链接时运行的代码会改变URL中的锚标签,所以我们可以从那里得到页码值。

 

$.getScript(     
  $.queryString(       
    document.location.href, { 'page':$.fragment().page }     
  )   
); 

 

这块代码有点复杂,所以我们把它分解成多行使其更清晰一些。为了得到正确的URL,我们使用了$.queryString函数,传入参数document.location.href来获得页面URL的主体部分,传入一个键值为page的JavaScript对象来构造querystring。通过调用$.fragment().page,我们可以从URL的锚标签部分得到正确的页码值。构造出正确的URL,我们就可以把它作为$.getScript的参数来发起AJAX请求了。

 

如果现在我们刷新页面并且点击这些链接,返回按钮依然可用。但是现在再点击返回按钮,fragmentChange事件将被触发,AJAX请求会更新产品列表,从而显示出正确的产品页。

 

书签收录和页面刷新

大功即将告成,不过页面上还有一点不如人意的地方。如果我们在浏览某一产品页时刷新了页面,我们依然只能看到第一页产品。如果我们收录了某一页到书签中,然后再打开它,也会有同样的问题。

 

解决这个问题的方法是,当页面的URL中存在锚标签时,在页面刷新时能够触发fragmentChange事件。为此,我们需要在pagination中在加入几行JavaScript代码。

 

if ($.fragment().page) {     
  $(document).trigger("fragmentChange.page");   
}

 

这段代码在页面刷新的时候看URL中是否有一个锚标签,如果有就触发fragmentChange事件,这样就可以加载正确的产品页了。

 

最终完整的pagination代码如下所示:

 

$(function () {       
  $('.pagination a').live("click", function () {           
    $.setFragment({ page: $.queryString(this.href).page });           
    $('.pagination').html('Page is loading...');           
    return false;       
  });       

  $.fragmentChange(true);       
    $(document).bind("fragmentChange.page", function () {           
    $.getScript($.queryString(document.location.href, { 'page': $.fragment().page }));       
  });       

  if ($.fragment().page) {           
    $(document).trigger("fragmentChange.page");       
  }   
}); 

 

现在我们可以通过AJAX的方式来对产品列表翻页,并且支持浏览器的前进和返回按钮,而且能够将其中某一页收录到书签里。

 

在我们的程序中,我们使用jQuery开发了分页功能,其实还有很多用户是使用Prototype的。如果你用ProtoType,Prototypeextensions程序库中也有类似的支持AJAX浏览记录的功能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值