我正在使用带有 twitter 引导程序的 select2 jquery 插件。它适用于较少数量的项目。但是当列表很大(超过 1500 项)时,它真的会变慢。它在 IE 中最慢。
Normal Dropdownlist 可以非常快速地处理超过 1500 个项目。这种情况有什么解决方法吗?
我正在使用带有 twitter 引导程序的 select2 jquery 插件。它适用于较少数量的项目。但是当列表很大(超过 1500 项)时,它真的会变慢。它在 IE 中最慢。
Normal Dropdownlist 可以非常快速地处理超过 1500 个项目。这种情况有什么解决方法吗?
即使在 IE8 中,您也可以通过对建议进行分页来使这项工作变得更好,
代码:
// 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,
});
},
});
})();
这里有 20000 个项目的工作示例:http: //embed.plnkr.co/db8SXs/preview
plnkr embed 不支持 IE8,因此请使用以下链接在 IE8 上试用: http ://run.plnkr.co/plunks/db8SXs/
我知道这是一个老问题,但我想分享对我有用的东西。如果您必须预先加载大列表(取决于您是从头开始还是在其他人的代码上构建,这可能更容易),请minimumInputLength
按照文档中的说明使用。在用户输入几个字符之前,不会显示巨大的选项列表。当实际选择 Select2 下拉菜单时,这大大降低了渲染它们时的性能损失。希望有帮助!
这是 Select2 v4 的工作版本
根据此处的答案:并对其进行修改以使搜索与 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/
编辑:小提琴改变了。
所以请记住,您正在以<option>
s 的形式将超过 1500 个实际元素加载到页面上,这最终也会损害页面性能。正如评论中的用户建议的那样,您可以通过对将返回您的值的后端服务进行 AJAX 调用来解决性能问题。
对我来说最简单和最短的作品是:
$(".client_id").select2({
minimumInputLength: 2
});
您可以根据需要更改 minimumInputLength 的值。
这样,select2 将不必显示整个列表,而是仅在输入固定数量的字符后才会显示结果。尽管您仍然在前端代码中拥有大量列表。
此外,如果您使用的是 allowClear,那么您必须像这样声明占位符:
$(".client_id").select2({
minimumInputLength: 2,
allowClear: true,
placeholder: '--Select Client--'
});
在此处查看文档http://select2.github.io/select2
如果您的数据仍然太大并且仍然存在性能问题,请使用 Ajax 方法。最好不要在select中加载太大的数据,而是使用Ajax for Select2 https://select2.org/data-sources/ajax
这是一个非常古老的问题和答案,甚至我们有更新版本的 select2。但如果有人也试图在 optgroup 中搜索。可以试试这个解决方案。
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
});
}
});
作为另一个更新,我想分享对我有用的东西,因为为这么旧的东西寻找支持变得越来越困难。我已经使用 npm 安装了 select 2,发现包含两个版本。默认版本require('select2')
不支持查询参数。需要完整版本require('select2/dist/js/select2.full')
,然后使用此处显示的代码对我使用 select 2 v4,data() 返回 16k 城市的列表
$(".select_2_cities").select2({
theme: "bootstrap",
data: data(),
multiple: true,
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
});
}
});