jQueryUI:自动完成大数据是悬挂浏览器

时间:2016-08-17 07:12:59

标签: javascript jquery jquery-ui autocomplete

我在我的项目中使用jQueryUI's autcomplete。我有一个自动完成文本,其中用户搜索的东西和相应的数据下拉。

使用小数据集,它工作正常。当数据集很大时会出现问题。我有几乎1L记录具有唯一值,我作为autocomplete的来源附加。

现在,只要用户在文本栏中输入搜索字符串,浏览器就会因为jQueryUI autocomplete的处理而挂起原因。

我想知道如何优化它或使其更快,以便borwser不会挂起。这是我创建的plunkr。这就是我要将源附加到自动完成的过程。

$("#tags").autocomplete({
      source: availableTags
});

5 个答案:

答案 0 :(得分:6)

而不显示所有50000条记录仅显示前10条。最小搜索字符长度从默认0增加到2



$(function () {
            var availableTags = [
              "ActionScript",
              "AppleScript",
              "Asp",
              "BASIC",
              "C",
              "C++",
              "Clojure",
              "COBOL",
              "ColdFusion",
              "Erlang",
              "Fortran",
              "Groovy",
              "Haskell",
              "Java",
              "JavaScript",
              "Lisp",
              "Perl",
              "PHP",
              "Python",
              "Ruby",
              "Scala",
              "Scheme"
            ];
            for (var i = 0; i < 50000; i++) {
                availableTags.push('abc' + i);
            }
            $("#tags").autocomplete({
                minLength: 2,
                source: function (request, response) {
                    var results = $.ui.autocomplete.filter(availableTags, request.term);

                    response(results.slice(0, 10));
                }
            });
        });
&#13;
    <link rel="stylesheet" href="//code.jquery.com/ui/1.12.0/themes/base/jquery-ui.css">

    <script src="https://code.jquery.com/jquery-1.12.4.js"></script>
    <script src="https://code.jquery.com/ui/1.12.0/jquery-ui.js"></script>

 <div class="ui-widget">
        <label for="tags">Tags: </label>
        <input id="tags">
    </div>
&#13;
&#13;
&#13;

答案 1 :(得分:1)

添加显示结果的限制,例如十。

答案 2 :(得分:1)

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>jQuery UI Autocomplete - Default functionality</title>
  <link rel="stylesheet" href="//code.jquery.com/ui/1.12.0/themes/base/jquery-ui.css">
  <link rel="stylesheet" href="/resources/demos/style.css">
  <script src="https://code.jquery.com/jquery-1.12.4.js"></script>
  <script src="https://code.jquery.com/ui/1.12.0/jquery-ui.js"></script>
  <script>
  $( function() {
    var availableTags = [
      "ActionScript",
      "AppleScript",
      "Asp",
      "BASIC",
      "C",
      "C++",
      "Clojure",
      "COBOL",
      "ColdFusion",
      "Erlang",
      "Fortran",
      "Groovy",
      "Haskell",
      "Java",
      "JavaScript",
      "Lisp",
      "Perl",
      "PHP",
      "Python",
      "Ruby",
      "Scala",
      "Scheme"
    ];
    var max= 10000;
    // change max to 1000000 ie. 1L and it hangs.
    for(var i=0;i<max;i++){
      availableTags.push(i+'');
    }

    $("#tags").autocomplete({
    source: function(request, response) {
        var results = $.ui.autocomplete.filter(availableTags, request.term);

        response(results.slice(0, 20));
    }
});
  } );
  </script>
</head>
<body>

<div class="ui-widget">
  <label for="tags">Tags: </label>
  <input id="tags">
</div>


</body>
</html>

请检查

答案 3 :(得分:1)

我遇到了同样的问题,并通过使用自定义函数重写_renderMenu函数来解决了该问题,该函数可以异步呈现项目列表。

首先,您定义一个异步渲染函数和一个用于停止异步渲染的函数(please read the API documentation,因此您知道自己在做什么):

let customACFunctions = {

    asyncRenderMenu: function(ul, data) {
        let batchSize = 20;
        let autoc = this;   //refers to the autocomplete widget.

        function renderNextBatch(){
            $(ul).find('li.autocomplete-spinner').remove();
            let j = 0;
            while (j < batchSize && data.length > 0) {
                autoc._renderItemData(ul, data.shift());
                j++;
            }
            //normally, the widget internals add this class to each list item, now 
            //we'll have to do it ourselves
            $(ul).find('li:not(.ui-menu-item)').addClass('ui-menu-item');
            if (data.length > 0) {
                //add an 'item' to indicate that the list is still being 'loaded'
                $(ul).append('<li class="ui-menu-item autocomplete-spinner"><a>Laden...</a></li>');
                customACFunctions._asyncRenderingTimeoutId = setTimeout(renderNextBatch, 1);
            }
        }
        renderNextBatch();
    },
    _asyncRenderingTimeoutId: null,
    stopAsyncRendering: function() {
        if (customACFunctions._asyncRenderingTimeoutId) {
            clearTimeout(customACFunctions._asyncRenderingTimeoutId);
            customACFunctions._asyncRenderingTimeoutId = null;
        }
    }
};

接下来,您将异步渲染功能分配给小部件:

$("#autocompleteId").data("ui-autocomplete")._renderMenu = customACFunctions.asyncRenderMenu;

接下来,当我们更改搜索查询时,我们还必须停止此异步呈现-我们的小部件不知道该异步呈现。 (否则,您的项目列表中会乱七八糟...)如果尚未为“搜索”事件定义事件处理程序,则可以执行以下操作:

$("#autocompleteId").on("autocompletesearch", customACFunctions.stopAsyncRendering);

如果您已为搜索事件定义了事件处理程序,那么请从该事件处理程序中调用此函数。

最好还是在用户选择一个项目时停止渲染。如果您已经为'select'事件定义了一个函数,则在事件处理程序中调用该函数。否则:

$("#autocompleteId").on("autocompleteselect", customACFunctions.stopAsyncRendering);

答案 4 :(得分:0)

我建议限制从本地设备以外的地方获取的数据。因为不显示它们并不意味着你没有为它们分配内存。虽然这样做也会有所帮助。 P.s:为我可怜的英语道歉