近期在项目中有用到搜索用户的功能,于是自己使用JQuery写了一个在输入框填写名字然后在下拉框中出现相对应的名字
一、思路
在取数据方面刚开始是有两个方案,第一个方案是在页面load的时候直接请求API将所有的用户名信息都取出来然后保存在数组中,然后在搜索时从中取数据。第二个方案是在搜索时根据输入框的信息实时调用API取数据。由于考虑到如果用户量很多的话在load页面请求数据势必会造成一定的影响,所以最后我决定用第二种方案。
那么在输入用户名时调用API我们肯定也要考虑多个方面,比如在输入用户名时,有些人不想输入完整姓名,输入一半就停止不输入怎么办;API在什么时候请求比较合理(如何减少API请求次数);用户名输入错误找不到又如果提醒用户;搜索到用户名,但是用户忘了选择下拉框的值,直接提交输入框中不完整的名字怎么办;
二、代码( jquery + coffeeScript)
1.核心代码块
ownerSearchInput: (e)->
t = this
i = 0
key = e.which
if $('.input-sm').val().length != 0 && key != 40 && key != 38 && key != 13
f = _.debounce(t.ajaxSearch , 500)
f()
if key == 40 && t.keyselectIdx < $($('#ownerSearchUl').children()).length
i = t.keyselectIdx
t.keyselectIdx += 1
if key == 38 && t.keyselectIdx > 0
i = t.keyselectIdx
t.keyselectIdx -= 1
if t.keyselectIdx > $($('#ownerSearchUl').children()).length
t.keyselectIdx = 0
$($('#ownerSearchUl').children()[i]).removeClass('ownerSearchLiActive')
$($('#ownerSearchUl').children()[t.keyselectIdx]).addClass('ownerSearchLiActive')
if key == 13
$('.input-sm').val($($('#ownerSearchUl').children()[t.keyselectIdx]).children('span').text())
t.shotName = $($('#ownerSearchUl').children()[t.keyselectIdx]).text().split($($('#ownerSearchUl').children()[t.keyselectIdx]).children('span').text())[0]
ajaxSearch: () ->
t = this
$.ajax
url: 'http://xxx.xxx?name=' + $('.input-sm').val()
type: 'GET'
dataType: 'json'
headers:
"Content-Type": "application/json"
beforeSend: (xhr) ->
xhr.setRequestHeader "Authorization", "Basic " + config.authen
success: (result, status, xhr)->
j = 0
if($('#ownerSearchUl').length>=1)
$('#ownerSearchUl').empty()
else
$('<ul id="ownerSearchUl"></ul>').appendTo($('.ownerSearchResult'))
$.each result,(cell,i) ->
if j == 0
$('<li class="ownerSearchLi ownerSearchLiActive">' + cell + '<span>' + i + '</span>' + '</li>').appendTo($('#ownerSearchUl'))
else
$('<li class="ownerSearchLi">' + cell + '<span>' + i + '</span>' + '</li>').appendTo($('#ownerSearchUl'))
j+=1
$('#ownerSearchUl').css('display','block')
error: (request, textStatus, errorThrown) ->
console.log(request.responseText)
console.log(textStatus)
console.log(errorThrown)
代码也不是很完全,但是这部分也是实现这个功能的核心了
首先在输入框输入内容(keydown)时触发onSearchInput事件,如果输入框内容不为空而且不是键盘操作(上下键和enter键)的时候调用ajaxSearch方法,该事件也就是调用API了。大家可以发现我在调用ajaxSearch方法时用到了_.debounce这个函数,在这里我简单讲解一下这个函数
_.debounce:
我们在上面的思路中有提到如何减少API请求次数,因为按照在输入框输入内容就调用API的话,这样就等于每输入一下字符就调用一次API,这显然是很不合理的,所以我们用到了debounce这个函数,在 JavaScript 中, debounce函数所做的事情就是,强制一个函数在某个连续时间段内只执行一次,哪怕它本来会被调用多次。我们希望在用户停止某个操作一段时间之后才执行相应的监听函数,而不是在用户操作的过程当中,浏览器触发多少次事件,就执行多少次监听函数。
这样的一个好处就是我们在一定时间内不断触发ajaxSearch方法时,debounce 总能阻止上一次的事件,这样等于在规定事件内我们就只会调用一次API,大大提高了效率
debounce函数接受两个参数,从上面的例子中可以看出,第一个参数是回调函数fn,第二个参数是规定要延迟的时间delay,当然在例子中我使用的是underscore的_.debounce,这个还支持第三个参数immediate
,表明回调函数是在一个时间区间的最开始执行(immediate
为 true
)还是最后执行(immediate
为 false
)。不过我也没用到,有兴趣的可以自己去研究一下。这里就不深究 了
言归正传,调用API之后将返回的数据以li的形式显示在输入框下面,这个html和css方面就不说了,然后就是要绑定键盘事件了,比如上下键聚焦在对应的li上(我是在li上面添加Active类说白了就是加个背景色什么的),点击enter键的时候将带有active类的li的值赋给input。
以上就是大致的思路了
还有一些问题比如用户输入错误提交了怎么办,输入不完整怎么办
这其实只要做一些验证都是不难解决的,哈哈哈,这里就不讲了
写得比较粗糙,请见谅