[英]addEventListener('click', function(), {once: true}) firing multiple times in the same position
[英]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.