如何使这个jquery函数更有效?

时间:2011-08-24 01:13:49

标签: jquery

我有一个结帐我玩的时候每个项目的数量输入旁边都有一些向上和向下箭头。

我有一些重复的代码,它看起来效率不高。希望你能提供帮助。

每个项目看起来像这样(请原谅我的非标准符合item_id属性)

<div class="qty_ctrl_wrap">
  <input class="bag_qty" type="text" value="4" item_id="532" name="product_quantity">
  <div class="arrows">
    <div class="more"></div>
    <div class="less"></div>
  </div>
</div>

这里是完整的jquery函数:

$('#checkout .arrows div').live('click',function(){

    var item_id = $(this).parent().prev('input').attr('item_id');
    var current_qty = $(this).parent().prev('input').val();

    if($(this).attr('class') == 'more') {

        var new_qty = parseInt(current_qty) + 1;

    } else {

        var new_qty = parseInt(current_qty) - 1;

    }

    // change the input on screen for visual reasons...
    $(this).parent().prev('input').val(new_qty);


    // submit the changes
        $.ajax({
        type: 'POST',
        url: '/backend/product_purchase_items.php',
        data: 'qty='+new_qty+'&item_id='+item_id,
        cache: false,
        success: function(data) {
          $('#product_purchase_items').html(data);
        }
        });     

});

如您所见,我重复了以下三次:

$(this).parent().prev('input')

我一直试图弄清楚如何将其放入变量中,因此我不必重复该代码。

但除此之外,它的工作方式是,如果你点击箭头3次,它会 3分开ajax帖子。理想情况下,在发送帖子之前会有一点停顿。

在提交帖子之前,如何进行300毫秒的暂停以查看箭头是否还有其他点击次数?

3 个答案:

答案 0 :(得分:5)

您可以使用setTimeout 去抖动事件:

$('#checkout .arrows div').live('click',function(){
    var $this = $(this),
        data = $this.data(),
        $item = $(this).parent().prev('input');


    if(data['debounce_timer']) {
        clearTimeout(data['debounce_timer']);
    }

    $item.val(function(i, value) {
        return +value + $this.hasClass('more') ? 1 : -1;
    });

    // Maybe you have to store a reference to the quantity (value) here. 
    // Otherwise you might get strange results when the arrow was just 
    // clicked again when the callback is executed.

    var timer = setTimeout(function() {
        $.ajax({
            type: 'POST',
            url: '/backend/product_purchase_items.php',
            data: {qty: $item.val(), item_id: $item.attr('item_id')}
            cache: false,
            success: function(data) {
              $('#product_purchase_items').html(data);
            }
        });    
    }, 150); // <-- try different times

    data['debounce_timer'] = timer;
});

改变/应该考虑的事情:

  • 在变量中缓存$(this).parent().prev('input')以便每次都不遍历DOM以再次找到相同的元素

  • 将函数传递给.val() [docs]并一次性更新值。

  • 使用一元+将字符串转换为数字,而不是parseInt。如果您使用parseInt,则必须将基数作为第二个参数传递(在您的情况下为10),以防止来自interpreting numbers with leading zeroes as octal numbers的JS。

  • 使用.hasClass() [docs]代替比较class属性。如果元素有多个类,则比较将失败。

  • 对象设置为data选项的值而不是字符串。这可确保数据正确编码。

  • 您真的应该使用HTML5 data attributes而不是自定义属性(item_id)。即使浏览器不支持HTML5(尚未),这也是更安全的方式。使用jQuery,您甚至可以通过.data()方法访问它们。

  • 使用setTimeout [MDN]延迟Ajax调用并在.data() [docs]中存储对计时器ID的引用。快速执行处理程序时,将使用clearTimeout [MDN]取消之前的计时器,以防止过多的Ajax请求。

答案 1 :(得分:2)

第一个问题的答案很简单:

var associatedInput = $(this).parent().prev('input');
// which you use like this:
var current_qty = associatedInput.val();

就实施稍有延迟而言,这是一种方法:

// following var declared outside your click handler, though not
// necessarily global because your code should probably be in a
// document ready handler:
var timerID = null;

// following within the click handler where your current $.ajax call is:
if (timerID != null) {
  clearTimeout(timerID);
}

timerID = setTimeout(function() {
                       timerID = null;
                       $.ajax(/*your existing ajax code/options here*/);
                     }, 300);

如果不明显,第一次调用click处理程序时,它将设置超时以延迟ajax调用。在第二次和随后的点击中,如果已经有计时器滴答,它将被清除(取消)并设置新的超时。因此,这将继续推迟ajax调用,直到最后一次点击后经过最少300毫秒。

答案 2 :(得分:1)

我会使用类似的东西:

var $input = $(this).closest("input.bag_qty");

此外,变量new_qty超出范围,您可以这样做:

var new_qty = $(this).hasClass('more') ? parseInt(current_qty, 10) + 1 : parseInt(current_qty, 10) - 1;