-1

我正在对超过 10000 行数据集进行实时搜索。我已经提到了可用的 dom 结构。尽管我尝试在一次输入后对每个结果进行实时搜索检查,但我的浏览器正在挂起。有没有其他有效的方法可以降低它的复杂性。

<label class="label">
    <input type="checkbox" name="123" value="">
</label>
<label class="label">
    <input type="checkbox" name="123" value="   General AUX"> General AUX
</label>
<label class="label">
    <input type="checkbox" name="123" value=" Annser"> Annser
</label>
<label class="label">
    <input type="checkbox" name="123" value=" LRIPL"> LRIPL
</label>
<label class="label">
    <input type="checkbox" name="123" value=" Soy Impulse"> Soy Impulse
</label>

** 是的,针对 DOM 进行实时搜索** JS 代码,我用于实时搜索

 $(".form-container #filter").keyup(function() {
 var filter = $(this).val(),
                    count = 0;
                if(filter.length>=2){
                // Loop through the comment list
                $(".label").each(function() {

                    // If the list item does not contain the text phrase fade it out
                    if ($(this).text().search(new RegExp(filter, "i")) < 0) {
                        $(this).fadeOut();

                        // Show the list item if the phrase matches and increase the count by 1
                    } else {
                        $(this).show();
                        count++;
                        }
                 });
                // Update the count
                var numberItems = count;
                // $(".popopup-header").text(count + " results");
                //$("#filter-count").text(count + "results"); 
              }
            });
4

3 回答 3

8

您可以通过三种不同的方式来提高实时 DOM 搜索的性能。(我将把渲染 10000 个 DOM 行的固有性能问题作为给定的;这个答案将只涵盖搜索及其结果。)使用 .indexOf() 而不是正则表达式等小细节也会有所帮助,但我猜这种精细的细节并不是你的瓶颈。

让搜索更快

实时搜索 DOM 总是比搜索简单的数据对象慢得多。我猜这是目前为止最大的性能瓶颈。

看起来您只匹配每行的单个字符串,这使事情变得更容易。如果你可以依赖你的行的顺序永远不会改变,那么你可以摆脱对这些字符串的简单数组的搜索,只需使用数组索引来指示你将隐藏或显示哪些 DOM 行(更多关于稍后)——但如果行顺序可能发生变化,您需要为每个行至少包含一个 ID,以便您可以将字符串与正确的行匹配。所以最简单的情况可能是

var search = function(searchString) {
var searchableRows = ["General AUX", "Ansser", "Etcetera", ...]
var matchedSearch = [];
for (var i=0; i<searchableRows.length; i++) {
  if (searchableRows[i].indexOf(searchString) > -1) {
    matchedSearch[i]=1;
  }
}
// you'll use matchedSearch[] later to control which rows are visible.

不经常运行搜索

无需在每次用户击键时都运行搜索,您可以对输入进行反跳以保证各个搜索之间至少有n毫秒。一些框架内置了去抖功能,但你自己的很简单。典型的插入示例可能来自 David Walsh,我无法改进:

// Returns a function, that, as long as it continues to be invoked, will not
// be triggered. The function will be called after it stops being called for
// N milliseconds. If `immediate` is passed, trigger the function on the
// leading edge, instead of the trailing.
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);
    };
};

更快地渲染结果

一个大的 DOM 操作比许多小的 DOM 操作便宜。并且你为了得到你想要的结果而改变 DOM 的次数越少越好。

因此,在搜索过程中逐步隐藏或删除 DOM 行的简单方法——这是肯定的。我能想到的两种处理这个问题的方法非常不同,老实说,我不确定哪个会有更好的性能。哪个更好可能归结为其他因素,例如 HTML 需要多么复杂,它是否具有您需要保留的 js 绑定,您可以在 javascript 中生成多少,等等。

所以策略 1:将结果 html 生成为一个大字符串,然后将其放入 DOM 以在单个操作中替换原始 HTML:

//assuming you have a filled matchedSearch array from above:
var searchResults = "";
for (var i=0; i<searchableRows.length; i++) {
  if (matchedSearch[i]) {
    searchResults = searchResults + '<label>...'+searchableRows[i]+'</label'>;
  }
}
document.getElementById('ResultsLocation').innerHTML(searchResults);

或者策略 2 是采取相反的方法:渲染完整列表一次,并尽量减少每次搜索后更改它的次数。同样,这将在您完成生成 matchSearch 数组之后:

var allLabels = $('.label'); // I'm being lazy and depending on jQuery in this example
for (var i=0; i<allLabels.length; i++) {
  if (matchedSearch[i]) {
    allLabels[i].removeClass('hidden');
  } else {
    allLabels[i].addClass('hidden');
  }
}

(在你如何显示这个方面还有其他可能的优化——我注意到你.fadeOut()目前正在使用;我不知道这是否比使用基于 CSS 类的动画慢,但这是值得的检查。有了这么多行,您可能会考虑忽略不必要的视觉效果。)

于 2016-01-27T16:04:57.660 回答
0

您触发对每个击键的搜索,这太多了。你应该推迟搜索。使用Lodash这样做很容易。另外,将正则表达式替换为 indexOf 更快。

您的新代码可能是:

 $(".form-container #filter").keyup(_.debounce(function() {
     var filter = $(this).val(),
                count = 0;
            if(filter.length>=2){
            // Loop through the comment list
            $(".label").each(function() {

                // If the list item does not contain the text phrase fade it out
                if ($(this).text().indexOf(filter)) < 0) {
                    $(this).fadeOut();

                    // Show the list item if the phrase matches and increase the count by 1
                } else {
                    $(this).show();
                    count++;
                    }
             });
            // Update the count
            var numberItems = count;
            // $(".popopup-header").text(count + " results");
            //$("#filter-count").text(count + "results"); 
          }
}, 400));
于 2016-01-27T14:30:59.713 回答
0

降低复杂性的一个步骤是在发送请求之前添加超时。如果在过期之前按下了更多键,则会附加要搜索的值。这样,您就不会为每个击键执行查询。

于 2016-01-27T14:27:53.920 回答