由于项目需求,需要通过下拉框选择用户,而系统中的用户有1w多人,通过chosen插件生成下拉框的话,会造成页面卡顿。
解决方案:
- 将用户数据存入localStorage
- 改造chosen插件,当用户搜索时,去localStorage获取匹配数据
具体思路:
- 从localStorage获取用户数据,保存到全局变量chosenUserList
- 如何没有数据,则通过ajax从数据库获取数据,并保存到localStorage和赋值给chosenUserList
- 生成chosen控件
- 监听chosen搜索框的input事件
- 当input事件触发时,设置定时器执行数据查询操作并更新chosen控件
select标签如下:
chosen-user用于初始化时识别,select-item用于保存选中项的值
<select name='' chosen-user select-item=''><option value=''></option></select>
具体代码如下:
<?php
// 引入jquery.chosen.js
css::import($zuiRoot . 'lib/chosen/chosen.min.css');
js::import($zuiRoot . 'lib/chosen/chosen.min.js');
?>
<script>
// 配置项
var ChosenUserOptions = {
no_results_text: '没有找到结果',
no_query_text: '请输入',
width:'100%',
allow_single_deselect: true,
placeholder_text_single: ' ',
placeholder_text_multiple: ' ',
search_contains: true
};
var chosenUserList = null;//用户列表
var chosenUserSearchKey = '';//用户搜索值
var chosenUserSearchTimer = '';//执行用户模糊搜索定时器
$(function(){
// 从localStorage获取用户列表
chosenUserList = JSON.parse(localStorage.getItem("chosenUserList"));
// 当数据不存在时,通过ajax去数据库获取,并存入localStorage
if (!chosenUserList) {
$.ajax({
url: "index.php?m=user&f=ajaxGetAllUser",
type: 'POST',
data: {},
async: false,
dataType: 'json',
success: function(data){
chosenUserList = data;
// 将json对象转换为字符串,再存入localStorage
localStorage.setItem("chosenUserList", JSON.stringify(data));
}
})
}
initChosenUser();
})
function initChosenUser(){
// 遍历所有需要生成chosen的select元素,这里我的标记是有属性chosen-user的select标签
$('[chosen-user]').each(function(){
// 获取已选选项的数组和option字符串
let selectObj = genChosenUserSelected($(this));
//添加选中项
$(this).html(selectObj.option);
//初始化控件
var chosen = $(this).chosen(ChosenUserOptions).on('change', function(){
changeChosenUser($(this));// 当值改变时,更新属性select-item
})
// console.dir(chosen.data('chosen'));
//监听搜索事件,当用户停止输入500毫秒后,执行操作
chosen.data('chosen').search_field.on('input', function(){
$this = $(this);
if (chosenUserSearchTimer) {
clearTimeout(chosenUserSearchTimer);
}
chosenUserSearchTimer = setTimeout(function() {
let selectObj = genChosenUserSelected($this.parents('.chosen-container').prev('select'));
let tmpOption = '';
let searchKey = $this.val(); // 搜索值
if ($.trim(searchKey) != '') {
for (let i in chosenUserList) {
if (chosenUserList[i].indexOf(searchKey) !== -1 && selectObj.array.indexOf(i) === -1) {
// 选项匹配搜索值 && 选项在在选中选项中不存在
tmpOption += `<option value="${i}">${chosenUserList[i]}</option>`;
}
}
}
chosenUserSearchKey = searchKey;// 保存用户输入
chosen.html(selectObj.option + tmpOption).trigger("chosen:updated");//更新chosen选项、会清空搜索框
chosen.data('chosen').search_field.val(chosenUserSearchKey).keydown();//将用户输入值放回搜索框,这里触发keydown可以设置搜索框宽度
}, 500);
})
})
}
/**
* 获取已选选项的数组和option字符串
* @param {Object} $select select Dom
*/
function genChosenUserSelected($select){
let selectOption = '<option value=""></option>';
let selectItemArr = $select.attr('select-item').split(',');
if (selectItemArr.length > 0) {
for (let i in selectItemArr) {
for (let account in chosenUserList) {
if (account == selectItemArr[i]) {
selectOption += `<option value="${account}" selected>${chosenUserList[account]}</option>`;
break;
}
}
}
}
return {
array: selectItemArr,
option: selectOption
}
}
/**
* 修改Select标签的属性
* @param {Object} $select select Dom
*/
function changeChosenUser($select){
if (Array.isArray($select.val())) {
$select.attr('select-item', $select.val().join(','));
} else {
$select.attr('select-item', $select.val());
}
}
</script>
$(select).chosen(option),将返回的内容保存到select元素的data('chosen')中
var obj = $(select).chosen(option);
console.dir(obj.data('chosen'));
search_field 为搜索框的input元素,其他属性不一一介绍,大家可以把它打到控制台自行查看