使用setTimeout

时间:2017-09-26 10:18:02

标签: javascript jquery filtering

我使用class='filt'编写了这个很好的代码用于各种表顶部的输入框,以允许根据这些输入过滤表。当然,大多数输入都超过1个字母,所以我想添加一个计时器或类似的去抖动功能。下面的工作正常,但是当我添加计时器时,我开始得到一个

  

“e.nodename未定义”

错误。任何想法?

<script>
    var typingTimer;
    var doneTypingInterval = 1000;
    $('.filt').on('keyup', function () {
        var children = $(this).parent().parent().find("input");
        clearTimeout(typingTimer);
        typingTimer = setTimeout(function () {
            $("#table1 tbody tr").show();
            for (var i = 0; i < children.length; i++) {
                var tableChild = children[i];
                if (tableChild.value) {
                    var valarr = tableChild.value.split(",,");  //multiple filter separator 
                    for (var az = 0; az < valarr.length; az++) {
                        if (valarr[az].charAt(0) == '~') {   //negation operator
                            var val2 = valarr[az].substr(1);
                            $("#table1 tbody tr:not(:not(:has(td:eq(" + tableChild.id + "):contains('" + val2 + "'),td:eq(" + tableChild.id + ") [value*='" + val2 + "'])))").hide();
                        } else {                              //standard filter
                            $("#table1 tbody tr:not(:has(td:eq(" + tableChild.id + "):contains('" + valarr[az] + "'),td:eq(" + tableChild.id + ") [value*='" + valarr[az] + "']))").hide();
                        }
                    }
                    $("#table1 tbody tr").eq(0).show();
                }
            }
            $(this).focus();  //annoying extra code for MS browsers
            var thistext = $(this).val();
            $(this).val('').val(thistext);
        }, doneTypingInterval);
    });
</script>

2 个答案:

答案 0 :(得分:1)

在启动计时器之前,只需将this放入另一个参数中,如下所示。因为setTimeout拥有自己的范围。

<script>
        var typingTimer;
        var doneTypingInterval = 1000;
        $('.filt').on('keyup', function () {
            var children = $(this).parent().parent().find("input");
            clearTimeout(typingTimer);

            //Get this into self
            var self =  this;

            typingTimer = setTimeout(function () {
                $("#table1 tbody tr").show();
                for (var i = 0; i < children.length; i++) {
                    var tableChild = children[i];
                    if (tableChild.value) {
                        var valarr = tableChild.value.split(",,");  //multiple filter separator 
                        for (var az = 0; az < valarr.length; az++) {
                            if (valarr[az].charAt(0) == '~') {   //negation operator
                                var val2 = valarr[az].substr(1);
                                $("#table1 tbody tr:not(:not(:has(td:eq(" + tableChild.id + "):contains('" + val2 + "'),td:eq(" + tableChild.id + ") [value*='" + val2 + "'])))").hide();
                            } else {                              //standard filter
                                $("#table1 tbody tr:not(:has(td:eq(" + tableChild.id + "):contains('" + valarr[az] + "'),td:eq(" + tableChild.id + ") [value*='" + valarr[az] + "']))").hide();
                            }
                        }
                        $("#table1 tbody tr").eq(0).show();
                    }
                }
                $(self).focus();  //annoying extra code for MS browsers
                var thistext = $(self).val();
                $(self).val('').val(thistext);
            }, doneTypingInterval);
        });
    </script>

答案 1 :(得分:1)

这是一个背景问题。您引用this,认为它指向.filt元素,但您没有意识到超时回调会将上下文更改为window

$('.foo').on('click', function() {
    this; //is the clicked element
    setTimeout(function() {
        this; //is window
    }, 1);
});

有几种方法可以引用不同的this。 jQuery的.bind()允许您将callbcak与您喜欢的任何this进行语境化,即元素。

$('.foo').on('click', function() {
    this; //is the clicked element
    setTimeout(function() {
        this; //is also element
    }.bind(this), 1); //<-- note bind()
});

或者,您也可以通过立即执行的函数将外部this作为函数参数传递给超时回调:

$('.foo').on('click', function() {
    this; //is the clicked element
    setTimeout((function(outer_this) { return function() {
        outer_this; //is also element
    }; })(this), 1);
});

或者只是在输入超时之前创建一个引用它的变量:

$('.foo').on('click', function() {
    var outer_this = this; //<-- cache outer scope
    this; //is the clicked element
    setTimeout(function() {
        outer_this; //is also element
    }, 1);
});