8

希望这对某人来说是一个快速而简单的方法。我对使用大量 javascript/jquery 相当陌生,并且我有以下设置从数据库中提取客户名称并在用户完成输入客户 ID 时显示它。

一切都很好,但它会在每个keyup进行搜索。我知道我可以将其更改为模糊,但我希望它可以延迟搜索。

这是当前代码:

function postData(){
    var id = $('#id').val();

    $.post('inc/repairs/events-backend.php',{id:id},   
        function(data){
        $("#display_customer").html(data);
    });
    return false;
}

$(function() {
    $("#id").bind('keyup',function() {postData()});
});

正如您所看到的,它绑定到每个 keyup,这意味着如果您搜索得太快,它可能会给您留下错误的结果,因为它仍在加载中。(即,如果未找到匹配项,则会显示错误,并且输入速度足够快,用户需要退格并重新输入最后一个数字)

有人可以协助在现有代码中添加延迟,并且如果可能的话,对您所做的更改进行一个小的解释,我宁愿不理解就只是复制和粘贴。

- - 编辑 - -

这是我完成的代码,谢谢大家!

function postData(){
    var id = $('#id').val();

    $.post('inc/repairs/events-backend.php',{id:id},   
        function(data){
        $("#display_customer").html(data);
    });
    return false;
}

$(function() {
    var timer;
    $("#id").bind('keyup input',function() {
        timer && clearTimeout(timer);
        timer = setTimeout(postData, 300);
    });
});
4

4 回答 4

8

您应该查看setTimeoutandclearTimeout函数:

$(function() {
    var timer;
    $("#id").on('keyup',function() {
        timer && clearTimeout(timer);
        timer = setTimeout(postData, 300);
    });
});

基本上我们所做的是,我们不是postData立即触发函数,而是将它传递给setTimeout,以便它在给定时间(在本例中为 300 毫秒)后触发。

setTimeout函数返回一个计时器 ID,然后我们可以将其传递clearTimeout给以取消该调用的运行。在每次按键时,在设置新计时器之前,我们首先检查是否设置了计时器。如果有,我们在开始新计时器之前取消旧计时器。


为了进一步增强这一点,您还可以在每次按键时中止您的 AJAX 调用,以防用户在 300 多毫秒后(在计时器触发之后,但在 AJAX 请求返回之前)键入内容。


PS你应该看看 Ben Alman 的油门/去抖动插件,它在这里可以很好地工作。

于 2013-01-23T03:20:58.190 回答
7

看看Underscore 的debounce函数——它使这种行为变得非常简单:

$(function() {
  $('#id').on('keyup input', _.debounce(postData, 500))
}

这样,postData只有在用户停止输入500ms(或您将 debounce 设置为任何内容)wait之后,才会调用

此外,除了击键(在现代浏览器中)之外,我还偷偷参加input活动以捕捉其他更改,例如复制/粘贴

于 2013-01-23T03:24:05.850 回答
2

我会在 keyup 上稍微延迟搜索,但您还需要中止最后一个请求,因为您无法预测它们将执行的顺序(或者您可以使用 ajax 队列)。

我将描述所有三个部分:

延迟

将 postData 回调包装在setTimeout. setTimeout存储as的返回值$("#id").data('timeout')并每次调用clearTimeout它,以便每个快速键入的字符串仅触发一次事件。

中止

将最后一个请求存储在$("#id").data('lastRequest')等等。每次postData调用,运行$("#id").data('lastRequest').abort()。将返回值存储 $.post()在该数据字段中。为了防止出错,初始化如下:

$("#id").data('lastRequest', {abort: function () {}));

队列

$("#id").data('lastRequest', true);
...
$.when($("#id").data('lastRequest')).then(function () {
   $("#id").data('lastRequest', $.post(...));
});
于 2013-01-23T03:23:24.683 回答
0

可能有更好的方法,但这是我的想法:

window.currentKeyup = 0;
$("#id").bind('keyup',function() {
    window.currentKeyup++;
    var keyup = window.currentKeyup;
    setTimeout(function(){
        if( keyup == window.currentKeyup ){
            postData();
        }
    },3000);
});
于 2013-01-23T03:25:18.573 回答