#javascript #jquery #jquery-ui
#javascript #jquery #jquery-пользовательский интерфейс
Вопрос:
Я использую фильтр jquery для поиска имен в большом списке имен. Он отлично работает с хорошей скоростью, когда я набираю в поле ввода. Но когда я нажимаю кнопку обратного пробела, чтобы очистить текст поиска, возникает задержка более 4s, когда осталось около 2 или 3 символов.
Я сделал демонстрацию, чтобы объяснить свою проблему
<input type="text" class="search">
<div class="list"></div>
<script>
// Get the list div
let $list = $('.list');
// Form a list of numbers from 1 to 8000
let listHtml = ''
for (let i = 0; i < 8000; i ) {
listHtml = `<div class="list_item"><div class="list_item_value c${i}">${i}</div></div>`;
}
$list.html(listHtml);
// Get all the list items
$listItem = $list.find('.list_item');
$('.search').on('keyup', function(e) {
// Get the search text
let text = $(this).val();
$listItem.filter(function() {
$(this).toggle($(this).find(`.list_item_value`).text().includes(text));
});
});
</script>
Я упростил свою проблему с этой демонстрацией, заменив текстовый поиск поиском по номеру.
Одним из способов устранения этой проблемы было бы отменить текущий процесс фильтрации jquery при нажатии обратного пробела. Но я не знаю, как это сделать. Пожалуйста, кто-нибудь, помогите мне это исправить.
Комментарии:
1. Для отображения 8000 элементов требуется больше времени, чем для их скрытия. Если проблема в том, что вы нажимаете backspace несколько раз, поэтому кажется, что это занимает намного больше времени, затем отмените ввод ключа (в любом случае, это хорошая идея). Вы не можете «отменить» фильтр, поскольку он не асинхронный, а js является однопоточным (поэтому ваша «отмена» не сработает до тех пор, пока. фильтр все равно завершен)
2. Вы также
.filter
неправильно используете (вы используете его как.each
), и отображение / скрытие каждого элемента по одному происходит очень медленно. Вместо этого верните результат .filter и выполните массовое обновление (показать / скрыть все элементы за один раз)
Ответ №1:
Рассмотрим следующий пример.
$(function() {
function makeItems(n, t) {
for (var i = 1; i < n; i ) {
$(t).append("<div class='list_item'><div class='list_item_value " i "'>" i "</div>");
}
}
var $list = $('.list');
makeItems(8000, $list);
$('.search').keyup(function(e) {
var text = $(this).val().toLowerCase();
$(".filtered").removeClass("filtered");
var search = (text.length > 0);
if (search) {
$(".list_item", $list).filter(function(index) {
return $(this).text().indexOf(text) === -1;
}).addClass("filtered");
}
});
});
.filtered {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="text" class="search">
<div class="list"></div>
Не слишком сильно отличается от вашего кода. Некоторое сокращение кода. Когда поиск завершен, существует условие, гарантирующее, что он не выполняется для пустого значения. Также мы каждый раз сбрасываем представление. Show, Hide и Toggle имеют упрощение и обратные вызовы, поэтому они могут быть медленнее в разы. Добавление / удаление класса выполняется очень быстро.
https://ryanpeden.com/javascript-indexof-vs-includes-performance/
Таким образом, хотя
includes
это будет немного, немного медленнее, потому что он должен проверять, передали ли вы ему регулярное выражение, на самом деле это не повлияет на скорость выполнения вашего кода. Вы должны использоватьindexOf
, если вам важно, где находится подстрока в исходной строке. Если вам все равно, просто вызовите includes, потому что это делает цель вашего кода более понятной.
В конце концов, это ваш вызов, если вы хотите использовать includes
или indexOf
для вашего сравнения.