jQuery 大型项目集的 Select2 性能
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15041058/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Select2 performance for large set of items
提问by Manish
I'm using select2 jquery plugin with twitter bootstrap. It's working fine for smaller number of items. But when the list is huge (more than 1500 items) it really slows down. It's slowest in IE.
我正在使用带有 twitter 引导程序的 select2 jquery 插件。它适用于较少数量的项目。但是当列表很大(超过 1500 项)时,它真的会变慢。它在 IE 中最慢。
Normal Dropdownlist works very fast with more than 1500 items. Are there any workarounds for this situation?
普通下拉列表处理 1500 多个项目的速度非常快。这种情况有什么解决方法吗?
回答by MarcusAsplund
You can make this work good even in IE8 with paginating the suggestions,
即使在 IE8 中,您也可以通过对建议进行分页来使这项工作顺利进行,
Code:
代码:
// Function to shuffle the demo data
function shuffle(str) {
return str
.split('')
.sort(function() {
return 0.5 - Math.random();
})
.join('');
}
// For demonstration purposes we first make
// a huge array of demo data (20 000 items)
// HEADS UP; for the _.map function i use underscore (actually lo-dash) here
function mockData() {
return _.map(_.range(1, 20000), function(i) {
return {
id: i,
text: shuffle('te ststr ing to shuffle') + ' ' + i,
};
});
}
(function() {
// init select 2
$('#test').select2({
data: mockData(),
placeholder: 'search',
multiple: true,
// query with pagination
query: function(q) {
var pageSize,
results,
that = this;
pageSize = 20; // or whatever pagesize
results = [];
if (q.term && q.term !== '') {
// HEADS UP; for the _.filter function i use underscore (actually lo-dash) here
results = _.filter(that.data, function(e) {
return e.text.toUpperCase().indexOf(q.term.toUpperCase()) >= 0;
});
} else if (q.term === '') {
results = that.data;
}
q.callback({
results: results.slice((q.page - 1) * pageSize, q.page * pageSize),
more: results.length >= q.page * pageSize,
});
},
});
})();
working example with 20000 items here: http://embed.plnkr.co/db8SXs/preview
这里有 20000 个项目的工作示例:http: //embed.plnkr.co/db8SXs/preview
plnkr embed does not support IE8 so try it out on IE8 with this link instead: http://run.plnkr.co/plunks/db8SXs/
plnkr embed 不支持 IE8,因此请使用此链接在 IE8 上尝试:http://run.plnkr.co/plunks/db8SXs/
回答by BammaHamma
I know it's an old question, but I wanted to share what worked for me. If you mustpre-load the big list(depending on if you're starting from scratch or building on someone else's code, this may be easier), use the minimumInputLength
as described herein the documentation. The huge list of options doesn't show until the user has typed a couple of characters. This greatly reduces the performance hit while rendering them when the Select2 dropdown is actually selected. Hope that helps!
我知道这是一个老问题,但我想分享对我有用的东西。如果您必须预加载大列表(取决于您是从头开始还是基于其他人的代码构建,这可能更容易),请使用文档minimumInputLength
中的此处所述。在用户输入几个字符之前,不会显示大量选项。当实际选择 Select2 下拉列表时,这大大降低了渲染它们时的性能损失。希望有帮助!
回答by Kelz
So keep in mind you are loading >1500 actual elements onto the page in the form of <option>
s, which can end up hurting page performance as well. As a user suggested in the a comment, you can solve the performance issue by making an AJAX call to a backend service that will return your values.
所以请记住,您正在以<option>
s的形式将超过 1500 个实际元素加载到页面上,这最终也会损害页面性能。正如用户在评论中建议的那样,您可以通过对将返回您的值的后端服务进行 AJAX 调用来解决性能问题。
回答by lofihelsinki
Here's a working version for Select2 v4
这是 Select2 v4 的工作版本
Based on the answer here: and modified it to make searching work with lo-dash
基于此处的答案:并对其进行了修改以使用 lo-dash 进行搜索
$(function () {
items = []
for (var i = 0; i < 1000; i++) {
items.push({ id: i, text : "item " + i})
}
pageSize = 50
jQuery.fn.select2.amd.require(["select2/data/array", "select2/utils"],
function (ArrayData, Utils) {
function CustomData($element, options) {
CustomData.__super__.constructor.call(this, $element, options);
}
Utils.Extend(CustomData, ArrayData);
CustomData.prototype.query = function (params, callback) {
var results = [];
if (params.term && params.term !== '') {
results = _.filter(items, function(e) {
return e.text.toUpperCase().indexOf(params.term.toUpperCase()) >= 0;
});
} else {
results = items;
}
if (!("page" in params)) {
params.page = 1;
}
var data = {};
data.results = results.slice((params.page - 1) * pageSize, params.page * pageSize);
data.pagination = {};
data.pagination.more = params.page * pageSize < results.length;
callback(data);
};
$(document).ready(function () {
$("select").select2({
ajax: {},
dataAdapter: CustomData
});
});
})
});
JsFiddle: http://jsfiddle.net/nea053tw/
JsFiddle:http: //jsfiddle.net/nea053tw/
Edit:Fiddle changed.
编辑:小提琴改变了。
回答by Maulik Vora
This is very old question and answer and even we have newer version of select2. but if someone is trying to search in optgroup too. can try this solution.
这是一个非常古老的问题和答案,甚至我们有较新版本的 select2。但如果有人也试图在 optgroup 中搜索。可以试试这个解决方案。
http://jsfiddle.net/na1zLkz3/4/
http://jsfiddle.net/na1zLkz3/4/
// Function to shuffle the demo data
var shuffle = function (str) {
return str.split('').sort(function () {
return 0.5 - Math.random();
}).join('');
};
// For demonstration purposes we first make
// a huge array of demo data (20 000 items)
// HEADS UP; for the _.map function i use underscore (actually lo-dash) here
var mockData = function () {
var array = _.map(_.range(1, 10), function (i) {
return {
id : i,
text: shuffle('te ststr ing to shuffle') + ' ' + i
};
});
return array;
};
var mockData1 = function () {
var array = _.map(_.range(10, 15), function (i) {
return {
id : i,
text: shuffle('te ststr ing to shuffle') + ' ' + i
};
});
return array;
};
var mockData2 = function () {
var array = _.map(_.range(15, 20), function (i) {
return {
id : i,
text: shuffle('te ststr ing to shuffle') + ' ' + i
};
});
return array;
};
// create demo data
var dummyData = mockData();
var dummyData1 = mockData1();
var dummyData2 = mockData2();
dummyData.push({
text: 'canada',
children: dummyData1
});
dummyData.push({
text: 'USA',
children: dummyData2
});
// init select 2
$('#ddlCar').select2({
data : dummyData,
// init selected from elements value
initSelection : function (element, callback) {
var initialData = [];
$(element.val().split(",")).each(function () {
initialData.push({
id : this,
text: this
});
});
callback(initialData);
},
// NOT NEEDED: These are just css for the demo data
dropdownCssClass : 'capitalize',
containerCssClass: 'capitalize',
// NOT NEEDED: text for loading more results
formatLoadMore : function() {return 'Loading more...'},
// query with pagination
query : function (q) {
var pageSize,
results;
pageSize = 20; // or whatever pagesize
var results = [];
if (q.term && q.term !== "") {
// HEADS UP; for the _.filter function i use underscore (actually lo-dash) here
var results = this.data;
var results = _.filter(results, function (e) {
if(typeof e.children != 'undefined')
{
subresults = _.filter(e.children, function (f) {
return (f.text.toUpperCase().indexOf(q.term.toUpperCase()) >= 0);
});
if(subresults.length > 0)
return true;
return false;
}
return (e.text.toUpperCase().indexOf(q.term.toUpperCase()) >= 0);
});
newresults = [];
for (var i = 0, len = results.length; i < len; i++) {
newresults[i] = {};
if(typeof results[i].text != 'undefined')
newresults[i].text = results[i].text;
if(typeof results[i].id != 'undefined')
newresults[i].id = results[i].id;
if(typeof results[i].children != 'undefined')
{
newresults[i].children = results[i].children;
newresults[i].children = _.filter(newresults[i].children, function (f) {
return (f.text.toUpperCase().indexOf(q.term.toUpperCase()) >= 0);
});
}
}
results = newresults;
} else if (q.term === "") {
results = this.data;
}
q.callback({
results: results.slice((q.page - 1) * pageSize, q.page * pageSize),
more : results.length >= q.page * pageSize
});
}
});
回答by Jaber Al Nahian
The easiest works for me is:
对我来说最简单的工作是:
$(".client_id").select2({
minimumInputLength: 2
});
You can change the value of minimumInputLength at your wish.
您可以根据需要更改 minimumInputLength 的值。
This way, select2 will not have to show whole list, rather it will bring result only after the fixed number of characters typed. Although you are still having the large array of list at front-end-code.
这样,select2 就不必显示整个列表,而是只有在输入固定数量的字符后才会显示结果。尽管您在前端代码中仍然拥有大量列表。
Also, if you are using allowClear, then you must declare placehodler like this:
另外,如果您使用的是allowClear,那么您必须像这样声明placehodler:
$(".client_id").select2({
minimumInputLength: 2,
allowClear: true,
placeholder: '--Select Client--'
});
Check the documentation here http://select2.github.io/select2