网站开发日志

2009年3月22日星期日

分享家:Addthis中国

document.ready还是不够快

我曾经在日志里介绍过jQuery的document.ready:

document.ready()和传统的方法<body onload=”load()”> 相似,不同的是onload()的方法是在页面加载完成后才发生,这包括DOM元素和其他页面元素(例如图片)的加载,因此,使用document.ready()方法的执行速度比onload()的方法要快。

document.ready()可以说是jQuery的一大特色,它不仅比传统的Javascript函数onload()要快,而且加上jQuery强大的选择器可以在不用修改HTML代码情况下(例如:不用在HTML标签加入onClick()函数来调用其它自定义Javascript函数)对Web页面中的各种元素和事件进行控制、实现和Web客户交互的作用。

可是有时document.ready()并非你想像的那么快,我在最近的一个project里就碰到这个问题。例如一个页面含有多个相似的链接,每一个链接的HTML代码大致如下:

<a rel="popin" href="/cart/?popin=yes&act=add&sku=xxx">
  <img src="/images/new/buynow.gif" border="0" />
</a> 

当这些链接被点击后,相对应的物品(sku)就会被加入购物篮,为让客户点击链接后不用离开当前页面,我使用了jQuery的ajax方法,从后台调用添加购物篮函数,然后返回xml响应,最后把xml携带的信息通过HTML层(layer)传递给客户。大致的jQuery+ajax代码如下:

$(document).ready(function(){
  $("a[rel^='popin']").click(function(){
    $.ajax({
      url: $(this).attr('href'),
      type: 'GET',
      dataType: 'xml',
      error: function(){
      alert('Error loading XML document');
    },
    success: function(xml){
      $('#cart_sum1').html($(xml).find('cart').text());
      $('#buynow-result').html($(xml).find('pop').text());
      $('#buynow-inform').show('slow');
      $('#cart_sum2').html($(xml).find('cart').text());        
    }
    });
    return false;
  });
});    

注意到我用了document.ready,试图在DOM ready的时候给这些链接(<a[rel^='popin'>)绑定点击事件控制。这在我的机子(windowxp+firefox3)里测试通过,但是在我老板的机子(redhat+firefox)上,有时会出现点击链接后跳出XML代码,原因很明显: 当她点击链接的时候,链接还没有被绑定事件控制,也就是说document.reday()还是不够快。

怎么解决?我有打算在链接代码里加入传统Javscript的onClick函数,这样当客户点击链接的时候,先调用onClick函数,然后在onClick函数里在调用ajax,应该就可以解决问题。今天想看看别人都是怎么解决这个问题,就用Google搜索了一下。找到这篇论坛问答,觉得说的挺有道理:

  • Using window.onload waits until the whole page is loaded.  (onload是在页面加载后起作用)
  • Using document.ready waits until the whole DOM is ready (document.ready是在DOM 准备好后起作用)
  • Having the script at the end of the body without document.ready, that doesn't wait. (把去掉document.ready的jQuery代码放在</body>前,无需等待)

准备明天到公司试试这种方法。其实把Javascript放在</body>前的说法以前也有看到过,Google的Analytics代码就建议放在</body>前。

Updated:(3/24/08)

经测试,第三种方法也不好用,主要问题是在页面没有完全加载完毕时,链接就已经被点击,这时</body>前的那一段jQuery代码还没有被加载,因此链接还没有被绑定ajax事件控制。

最终的解决办法是,把上面那段jQuery代码写出一个函数,反正header里,然后结合传统Javascript onClick函数,在链接被点击时直接调用header里函数。具体更改如下:

1. jQuery函数 (这段函数被放在header里)

function ajax_add(url_str){//把jquery代码写成一个函数
   $.ajax({
     url: url_str,
     type: 'GET',
     dataType: 'xml',
     //timeout: 5000,
     error: function(){
       alert('Error loading XML document');
     },
     success: function(xml){
       $('#cart_sum1').html($(xml).find('cart').text());
       $('#buynow-result').html($(xml).find('pop').text());
       $('#buynow-inform').show('slow');
       $('#cart_sum2').html($(xml).find('cart').text());
     }
   });
}

2. 链接代码:

<a onClick="add_ajax('/cart/?popin=yes&act=add&sku=xxx')" href="#">
  <img src="/images/new/buynow.gif" border="0" />
</a> 
注意:链接直接加入onClick事件控制,而不在页面加载后绑定事件控制。这样就可以避免链接被点击时,事件还没有绑定的问题。

标签: ,

相关文章:

3 条评论:

  • 前几天在一本书上看到了 onload 和 .ready 的区别!!就是这个样子的,但具体的不太记得了!!

    作者 Blogger xiaorsz, 时间 2009年3月24日 下午12:51  

  • onload 不如document.ready快是肯定的,但是现在的问题是document.ready在有些情况下还是不够快的,就比如文中的例子。
    另外,文中介绍的第三种方法(去掉document.ready,把
    jquery代码放在body的最后面)经测试也是解决不了问题。具体的解决方法,请参考本文的更新。

    作者 Blogger D Cai, 时间 2009年3月24日 下午5:14  

  • 好文章,把問題描述的很清楚,我今天正好遇到這問題,後來也是用onClick的方式解決!

    作者 Blogger Joe's Blog 資訊.數位學習.生活, 时间 2009年10月20日 上午10:52  

发表评论

指向此帖子的链接: