繁体   English   中英

addEventListener 在同一输入上多次执行 function

[英]addEventListener executing function multiple times on same input

我打算构建一个自动完成搜索,搜索大约包含 12,000 多个数据的建议数据。 jquery 从搜索框中获取值,搜索数据数组并将建议值存储在数组中,该数组将进一步用于填充建议。

<input type="text" id="Search_box" placeholder="Search Data">

$('#Search_box').on('input', function () {
    suggester(document.getElementById("Search_box"));
});

下面的 function 从搜索框中获取输入值并搜索包含 12,000 多条记录的 search_array,并给出包含这些字符的数据列表作为建议。

function suggester(searchElement) {

var init;
searchElement.addEventListener("input", function(e) {
        var x, y, i, val = this.value;
        closeAllLists();
        if (!val) { return false;}
        init = -1;

        var search_value = $('#Search_box').val();
        suggest_data = [];
        re = new RegExp("\\b\\w*" + search_value + "\\w*\\b", "ig");
        for (i = 0; i < search_array.length; i++) {
                if(search_array[i].match(re))
                         suggest_data = suggest_data.concat(search_array[i].match(re));
        }

        x = document.createElement("DIV");
        x.setAttribute("id", this.id + "autocomplete-list");
        x.setAttribute("class", "autocomplete-items");
        x.setAttribute("onClick", "this.setSelectionRange(0, this.value.length)");
        this.parentNode.appendChild(x);

        for (i = 0; i < suggest_data.length; i++) {
                y = document.createElement("DIV");
                val = truncate(suggest_data[i],30);
                reg = new RegExp(search_value, "ig");
                n = val.search(reg);
                res = suggest_data[i].substr(n,search_value.length);
                val = val.replace(res, '<span class="text_highlighter">'+res+'</span>');
                y.innerHTML = val;
                y.innerHTML += "<input type='hidden' value='" + suggest_data[i]  + "'>";
                y.addEventListener("click", function(e) {
                        searchElement.value = this.getElementsByTagName("input")[0].value;
                        closeAllLists();
                        $('#Search_box').focus();
                });
                x.appendChild(y);
                $('#Search_box').focus();
        }
});

searchElement.addEventListener("keydown", function(e) {
        var x = document.getElementById(this.id + "autocomplete-list");
        if (x) x = x.getElementsByTagName("div");
        if (e.keyCode == 40) {
            init++;
            addActive(x);
        } else if (e.keyCode == 38) { //up
            init--;
            addActive(x);
        } else if (e.keyCode == 13) {
            e.preventDefault();
            if (init > -1) {
                if (x) x[init].click();
            }
        }
});
function addActive(x) {
    if (!x) return false;
    removeActive(x);
    if (init >= x.length) init = 0;
    if (init < 0) init = (x.length - 1);
    x[init].classList.add("autocomplete-active");
}
function removeActive(x) {
    for (var i = 0; i < x.length; i++) {
        x[i].classList.remove("autocomplete-active");
    }
}
function closeAllLists(elmnt) {
    var x = document.getElementsByClassName("autocomplete-items");
    for (var i = 0; i < x.length; i++) {
        if (elmnt != x[i] && elmnt != searchElement) {
            x[i].parentNode.removeChild(x[i]);
        }
    }
}
document.addEventListener("click", function (e) {
        closeAllLists(e.target);

});

}

但是,当单击退格键时,这种方法会减慢速度。 addEventListener function 被多次触发,因此它在建议的 function 内循环以给出结果。 例如,如果输入 ASD 并且如果进一步键入退格键,则它在给出结果时开始减慢。 应该怎么做才能加快搜索速度?

在每次eventListener keydown触发您的autocomplete function。 当有人单击backspace时,您会同时得到一堆keydown's ,而现在,这意味着您正在同时运行 function 多次。 这就是减缓一切的原因。

例如,如果我输入“Hello my name is”然后删除整个字符串,我会触发您的搜索 16 次,搜索 12,000 x 16 条记录。 你可以开始明白为什么这会成为一个问题。

去抖 function 很容易解决这个问题,因为它设置了再次运行之间的延迟。 IE。 如果有人刚刚擦除了整个字符串,它可能只触发一次。

这是一个很好的去抖 function 示例:

    // http://davidwalsh.name/javascript-debounce-function
    function debounce(func, wait, immediate) {
        var timeout;
        return function() {
            var context = this, args = arguments;
            var later = function() {
                timeout = null;
                if (!immediate) { func.apply(context, args); }
            };
            var callNow = immediate && !timeout;
            clearTimeout(timeout);
            timeout = setTimeout(later, wait);
            if (callNow) { func.apply(context, args); }
        };
    }

这就是你如何在你的代码上实现它以实现自动完成:

searchElement.addEventListener("keydown", debounce(function(e) {
        var x = document.getElementById(this.id + "autocomplete-list");
        if (x) x = x.getElementsByTagName("div");
        if (e.keyCode == 40) {
            init++;
            addActive(x);
        } else if (e.keyCode == 38) { //up
            init--;
            addActive(x);
        } else if (e.keyCode == 13) {
            e.preventDefault();
            if (init > -1) {
                if (x) x[init].click();
            }
        }
}, 500)); // Time set here as callback for how often it should be run, change this to whatever you want the time delay to be.

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM