Javascript 当用户输入时,如何防止键控功能滞后

Javascript 当用户输入时,如何防止键控功能滞后,javascript,jquery,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

我正在尝试在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();
        }
    });
});
$('input')。在('keyup',function()上{
var searchTerm=$(“输入”).val().toLowerCase();
$('.item')。每个(函数(){
if($(this).filter('[data text*='+searchTerm+']')).length>0 | | searchTerm.length<1){
$(this.parent().show();
}否则{
$(this.parent().hide();
}
});
});
每次用户输入时,都会将其与
.item
divs的数据属性值进行比较。如果该元素的数据属性包含搜索查询,则将显示该查询,否则将隐藏该查询

这在Chrome中工作得很好,但是在Safari中,由于某些原因,当用户键入时,它确实很滞后

有办法解决这个问题吗

大约有1400个div(
.item
),每个元素的
数据文本
属性只有大约10-20个字符

编辑,通过删除
.show()
.hide()
-并替换为本机Javascript解决方案进行修复 我以前也遇到过类似的问题,我想您可能想尝试添加一个名为“去盎司”的东西,它基本上会在执行任何流程之前增加延迟。在
keyup
的情况下,它将等待用户停止键入任何设定的时间量(比如0.5秒),然后执行该过程(搜索或任何操作)。如果不使用debounce,它将在用户每次触发
keyup
事件时执行搜索

你可以搜索关于如何去Bounce的文章,我想有很多。但本质上它使用JS的
setTimeout
cleartimout
函数

以下是我发现的第一篇文章:

如何使用此功能?简单地说,只需添加实际函数(搜索函数)作为第一个参数,在第二个参数中添加延迟(微秒),然后使用.call()函数(为什么这样做?因为解盎司将返回一个函数)。我猜是这样的:

$('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();
});
$('input').on('keyup', debounce(function(){
    ...
},500));
它是如何工作的? 你可以在文章中读到它们,或者在StackOverflow中找到答案,这是我得到的

但是如果我用我自己的话,基本上你首先需要了解的是
setTimeout
在调用函数之前设置一个计时器,然后
cleartimout
取消该计时器。现在在去盎司中,您可以看到在任何
设置超时之前有一个
清除超时
。因此,每次触发keyup事件时,它基本上都会取消上次设置的超时(如果有),然后再设置一个新的超时。本质上,它会将计时器重置为每次触发事件时所设置的值

例如:

  • 用户想要搜索“abc”
  • 他们输入“a”->去盎司设置一个500毫秒的计时器,然后调用 实际搜索“a”
  • 在500毫秒之前,用户键入“b”,因此解盎司将取消“a”搜索,转而搜索“ab”,同时在执行此操作之前还将计时器设置为500毫秒
  • 在500毫秒之前,用户键入“c”,因此取消“ab”搜索,添加500毫秒计时器搜索“abc”
  • 用户在500毫秒前停止输入,现在反盎司实际上调用“abc”搜索
  • 这会导致什么结果?搜索的繁重处理只对“abc”执行一次,您也可以将加载器或其他东西放到这个繁重的处理过程中,这样用户看起来会更好一些

    一些快速修复:

    • 整理div,然后在每次
      之后的单个语句中显示/隐藏,而不是每次迭代
    更改DOM的成本相对较高,因此在单个语句中进行更改可以极大地提高性能

    • 如果这是
      则更改为
      div
      s
    表需要在小的更改时重新呈现整个表。固定的单元格大小会有所帮助。这个问题不是这样的,只是一般性的改进

    • 使用内存中的筛选器,而不是读取每个项的DOM
    读取DOM要比在内存中慢得多(当然在内存中使用更多内存)。例如,筛选
    .data()
    而不是
    [data-]
    ,因为它将在内存中使用。这在Chrome中可能很快,因为Chrome可能正在缓存
    [data-
    属性,因此Chrome可能没有改进

    • 取消对输入事件的缓冲,使其仅在用户完成键入时发生
    等待用户“完成”键入,然后运行操作

    • 利用你的优势
    虽然是边缘情况,但这条线

    if ($(this).filter('[data-text *= ' + searchTerm + ']').length > 0 || searchTerm.length < 1)
    
    示例显示了这一点

    函数a(){console.log(“a”);返回true;}
    函数b(){console.log(“b”);返回true;}//b()不需要存在
    
    如果(a()| | b())console.log(“c”)
    谢谢,它确实稍微提高了性能。当调用该函数时(即使在500毫秒去Bouncer之后)仍然有一些疯狂的延迟。很高兴它能帮上忙,那么接下来就是改进搜索函数本身,请参阅其他答案,您将找到一些建议
    if ($(this).filter('[data-text *= ' + searchTerm + ']').length > 0 || searchTerm.length < 1)
    
    if (searchTerm.length < 1 || $(this).filter('[data-text *= ' + searchTerm + ']').length > 0)