异步筛选搜索(下面简称搜索)是使用ajax发送搜索请求,可追回多个条件,应用的场景很多,比如:百度招聘,逻辑是只有在用户点击相关条件时触发重新请求,只请求内容,从而可以减少http请求和流量。
比如要完成上面百度招聘的搜索功能,先从简单的入手吧~
第一阶段 - 变量
思路是使用js记录下相应的几个变量,然后给元素绑定点击事件,并写入相关的变量,然后发送请求,发送请求的时候带上这些变量,如:
var 月薪 = null;
var 福利 = null;
var 地区 = null;
...
// 单选
$('月薪').on('click', function(){
// 让其他同级的类移除高亮className
// 给当前点击元素添加高亮className
// 让变量等于当前点击元素的参数
月薪 = $(thi).data('id');
// 发送请求
});
// 多选
$('福利').on('click', function(){
// 给当前点击元素toggle高亮className
// 查找当前元素所有的同级的高亮元素,并生成一个以参数为值的数组赋予变量
var ids = $(this).siblings('.高亮className').map(function(){
return $(this).data('id');
}).get().join(',');
福利 = ids;
// 发送请求
});
...
var 发送请求 = function(){
$.ajax({
...
data: {
福利: 福利,
月薪: 月薪,
...
}
});
}
在线demo
第二阶段 - 委托
在第一阶段的基础上考虑到委托事件,声明一个缓存对象cache用来存放异步请求时的数据,给所有筛选条件的可点击元素添加data-param-name=参数名用来写入缓存的key,添加data-param-type用来控制选择的类型,比如单选、多选等,添加data-value为选中值,这样就可以写委托了,比如:
// 操作高亮的类
// 发送请求
});
var 请求 = function(){
$.ajax({
data: cache,
});
}
在线demo
第三阶段 - 插件化
当完成了第二阶段后,发现当筛选的条件越来越多,类型越来越多时,很不好处理,并且还会出现重复请求的bug(当在上一个请求还没有完成又点击触发下一个请求),于是我想把搜索+请求这块写一个公用的方法。。。
搜索插件(暂且这么叫吧)只提供设置数据,删除数据,获取数据,发送请求的功能,然后自己逻辑代码就可以写那些什么多选啊、单选啊、文本框啊、下拉什么的了,可是你会发现逻辑代码要远远的大于搜索插件的代码,是的,但起码思路比较明确了,谁只做谁的事~
完整的例子
res.items = res.items || [];
if(res.items.length){
$.each(res.items, function(){
html += '
if(XXOO.get('query')){
html = html.replace(new RegExp(XXOO.get('query'), 'g'), function($0){
return ''+ $0 +'';
});
}
} else {
html = '
return '
var renderPage = function(res){
var page_size = parseInt(XXOO.get('page_size'), 10) || 10;
var pageCount = Math.ceil(res.total / page_size);
var page = parseInt(XXOO.get('page'), 10) || 1;
var str = '';
var i = 1;
if (pageCount > 1 && page
if (page > 1) {
str += '';
} else {
str += '上一页';
}
if (pageCount
for (i; i
if (page === i) {
str += '' + i + '';
} else {
str += '';
}
}
} else {
var start, end;
if (page === 1) {
str += '1';
} else {
str += '';
}
if (page > 4) {
str += '...';
}
if (page
start = 1;
} else {
start = page - 2;
}
if (page > (pageCount - 4)) {
end = pageCount;
} else {
end = page + 3;
}
for (var i2 = start; i2
if (i2 !== 1 && i2 !== pageCount) { //避免重复输出1和最后一页
if (i2 === page) {
str += '' + i2 + '';
} else {
str += '';
}
}
}
if (page
str += '...';
}
if (page === pageCount) {
str += '' + pageCount + '';
} else {
str += '';
}
start = end = null;
}
if (page
str += '';
} else {
str += '下一页';
}
str = '
return str;
}
var XXOO = new Search({
url: '/api/search/index',
success: function(res){
var html = '';
html += renderTpl(res);
html += renderPage(res);
$('#J-write').html(html);
},
error: function(){
$('#J-write').text('出错了');
},
beforeSend: function(){
$('.mask').stop().fadeIn();
},
complete: function(){
$('.mask').stop().fadeOut();
}
});
// 单选
$('.J-param').on('click', 'li', function(){
var id = $(this).data('id');
var type = $(this).data('type');
$(this).addClass('current').siblings().removeClass('current');
if(!id){
XXOO.del(type);
} else {
XXOO.set(type, id);
}
XXOO.request();
});
// 多选
$('.J-params').on('click', 'li', function(){
var id = $(this).data('id');
var type = $(this).data('type');
var ids;
// 处理是否点击的默认,如果是默认则清除其他的
// 不是默认
if(id){
$(this).toggleClass('current');
ids = $(this).parent().children('.current').map(function(){
return $(this).data('id');
}).get().join(',');
// 如果一个高亮的标签也没有
if(!ids){
$(this).parent().children().eq(0).addClass('current');
XXOO.del(type);
} else {
$(this).parent().children().eq(0).removeClass('current');
XXOO.set(type, ids);
}
} else {
XXOO.del(type);
$(this).addClass('current').siblings().removeClass('current');
}
XXOO.request();
});
// 分页大小
$('#J-page_size').on('change', function(){
XXOO.set('page_size', this.value).set('page', 1).request();
});
// 总数
$('#J-total').on('change', function(){
XXOO.set('total', this.value).set('page', 1).request();
});
// 关键词
$('#J-query').on('blur', function(){
XXOO.set('query', this.value);
});
// 搜索
$('#J-btn').on('click', function(){
XXOO.request();
});
// 分页
$('#J-write').on('click', '.ui-page a', function(){
XXOO.set('page', this.getAttribute('data-page')).request();
return false;
});
// 快速跳页
var $quickPage = $('#J-quick-page');
$('#J-quick-btn').on('click', function(){
var value = $quickPage.val();
if(!value){
$quickPage.focus();
} else if(!/^d+$/.test(value)){
$quickPage.focus().select();
} else {
value = parseInt(value, 10) || 1;
XXOO.set('page', value).request();
}
});
上面没有提供php处理脚本这个非常的简单就不介绍了。