如何防止用户键入时 keyup 功能滞后

tri*_*ddd 2 javascript jquery

我正在尝试在 jQuery 中创建一个搜索功能:

$('input').on('keyup', function(){
    var searchTerm = $("input").val().toLowerCase();
    $('.item').each(function(){
        if ($(this).filter('[data-text *= ' + searchTerm + ']').length > 0 || searchTerm.length < 1) {
            $(this).parent().show();
        } else {
            $(this).parent().hide();
        }
    });
});
Run Code Online (Sandbox Code Playgroud)

每次用户输入内容时,都会将其与.itemdiv 的数据属性值进行比较。如果该元素的数据属性包含搜索查询,则会显示它 - 否则隐藏。

这在 Chrome 中工作得很好,但在 Safari 中,由于某种原因,当用户打字时,它确实很滞后。

有没有办法来解决这个问题?

大约有1400个div( .item),data-text每个元素的属性只有10-20个字符左右

编辑,通过删除.show().hide()- 并用本机 Javascript 替换来修复

小智 6

解决方案

我以前遇到过类似的问题,我想你可能想尝试添加一些名为“debounce”的东西,这基本上在执行任何过程之前添加了延迟。在这种keyup情况下,它将等待用户停止输入任何设定的时间(假设 0.5 秒),然后执行该过程(搜索或其他)如果您不使用反跳,它将每次执行搜索用户触发keyup事件的时间。

你可以搜索一下如何做debounce的文章,我想有很多。但本质上它利用了JS的setTimeoutand功能clearTimeout

这是我发现的第一篇文章:https://levelup.gitconnected.com/debounce-in-javascript-improve-your-applications-performance-5b01855e086

const debounce = (func, wait) => {
let timeout;

  return function executedFunction(...args) {
    const later = () => {
      clearTimeout(timeout);
      func(...args);
    };

    clearTimeout(timeout);
    timeout = setTimeout(later, wait);
  };
};
Run Code Online (Sandbox Code Playgroud)

如何使用这个功能呢?简单,只需添加您的实际函数(搜索函数)作为第一个参数,并在第二个参数中添加延迟(微秒),然后使用 .call() 函数(为什么这样做?因为 debounce 会返回一个函数) 。所以我猜是这样的:

$('input').on('keyup', function(){
    var searchTerm = $("input").val().toLowerCase();
    debounce(function(){
        $('.item').each(function(){
            if ($(this).filter('[data-text *= ' + searchTerm + ']').length > 0 || searchTerm.length < 1) {
                $(this).parent().show();
            } else {
                $(this).parent().hide();
            }
        });
    }, 500).call();
});
Run Code Online (Sandbox Code Playgroud)

这就是我将如何做到的,因为这样我就可以将 debounce 之外的一些内容添加到 keyup 事件中,但是您可以将 debounce 返回的函数放入一个变量中,然后将其与 keyup 绑定(如文章中所示),或者直接将去抖放在 keyup 中,如下所示:

$('input').on('keyup', debounce(function(){
    ...
},500));
Run Code Online (Sandbox Code Playgroud)

它是如何运作的?

你可以在文章中阅读它们,或者在 StackOverflow 中找到答案,这就是我得到的有人可以解释一下 Javascript 中的“debounce”函数吗

但如果用我自己的话来说,基本上你首先需要理解的是setTimeout在调用函数之前设置一个计时器,并clearTimeout取消该计时器。clearTimeout现在在 debounce 中你可以看到在any 之前有一个setTimeout. 因此,每次触发 keyup 事件时,它基本上都会取消上次设置的超时(如果有),然后设置新的超时。本质上,每次触发事件时,它都会将计时器重置为您设置的值。

例如:

  1. 用户想要搜索“abc”
  2. 他们输入“a” -> 在调用“a”的实际搜索之前,去抖动设置了 500ms 的计时器
  3. 在 500ms 结束之前,用户输入“b”,因此去抖取消“a”搜索,并搜索“ab”,同时在执行之前设置 500ms 的计时器
  4. 在500ms还没到之前,用户输入“c”,所以取消“ab”搜索,添加一个500ms的定时器来搜索“abc”
  5. 用户停止输入直到 500 毫秒结束,现在去抖动实际上调用了对“abc”的搜索

这会带来什么结果呢?搜索的繁重处理仅对“abc”完成一次,您也可以将加载程序或其他东西放入此繁重处理中,这样对用户来说看起来更好