【问题标题】:jQueryUI: Autocomplete with large data is hanging browserjQueryUI:大数据的自动完成正在挂起浏览器
【发布时间】:2016-08-17 07:12:58
【问题描述】:

我在我的项目中使用jQueryUI's autcomplete。我有一个自动完成文本,用户在其中搜索某些内容,相应的数据会出现在下拉列表中。

使用小型数据集,它运行良好。当数据集很大时,就会出现问题。我有近 1L 条具有唯一值的记录,我已将它们作为源附加到 autocomplete

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

我想知道如何优化它或使其更快,以使浏览器不会挂起。这是我为玩而创建的plunkr。这就是我正在做的将源附加到自动完成。

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

【问题讨论】:

    标签: javascript jquery jquery-ui autocomplete


    【解决方案1】:

    只显示前 10 条记录,而不是显示所有 50000 条记录。最小搜索字符长度从默认的 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));
                    }
                });
            });
        <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>

    【讨论】:

      【解决方案2】:

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

      【讨论】:

      • 你能分享我如何设置它。
      【解决方案3】:
      <!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>
      

      请检查一下

      【讨论】:

      • 我同意与服务器端合作效率更高,而不是从服务器获取所有缺少的数据,他应该使用 like 或其他一些 Sql 查询属性获取类型字符串上的数据
      【解决方案4】:

      我遇到了同样的问题,并通过使用异步呈现项目列表的自定义函数覆盖 _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);
      

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

      最好也是在用户选择项目时停止渲染。如果您为“选择”事件定义了一个函数,则在您的事件处理程序中调用此函数。否则:

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

      【讨论】:

        【解决方案5】:

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

        【讨论】:

          【解决方案6】:

          由于数据量大,有时会出现这个问题。加载大量数据时浏览器挂起,

          在这里,第一个过滤器将对数组进行切片,并从整个数据中返回确定的准确值。

          $("#postcode").autocomplete({
              source: function (request, response){
                  var results = $.ui.autocomplete.filter(your_array,request.term);
                  response(results.slice(0, 10));
              }
          });
          

          希望这对你有用

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2016-03-05
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-06-24
            • 1970-01-01
            • 2014-09-12
            相关资源
            最近更新 更多