功能的要求是:在用户输入文本的时候发送到服务器,然后在搜索栏下面生成下拉框,点击下拉框的内容触发搜索,注意交互的效果,鼠标移入高亮显示,只有输入时才显示下拉框,点击下拉框和其它空白处隐藏,类似于百度搜索的效果
这是一个比较经典的功能,因为是通过监听输入框的onchange事件实现的,触发频率非常高几乎是实时的,当然我们不可能实时去请求后台接口,而是用逻辑去判断空隙时间,也就是使用setTimeout延时请求,也就是经常被称之为防抖的技术,处理完这个问题之后,剩下的就是渲染列表,绑定点击事件和鼠标悬停效果,和焦点的丢失事件,所以虽然是一个小功能,想做好还不是很容易,把任务分解一下,具体可以分为三步
1.监听输入框的onchange事件,在空隙时间中请求服务器
2.拿到的列表数据渲染到dom,鼠标移入高亮点击要发出搜索请求
3.如果输入框的焦点丢失了要隐藏下面的内容
部分源码如下,使用中间变量current取前一次的值,每一次输入框的变动之后的0.5秒判断,判断前一次值和当前值如果不相等就发送请求
//监听的逻辑
function listenInput() {
let current = ''
$('input').keydown(function (event) {
setTimeout(function () {
if (current != $('input').val()) {
getRequest(null, app.GetApi("GetKeywords"), {
para: $('input').val()
},
(res) => {
if (res.Result.length) {
renderKeywordList(res.Result);
}
}
);
} else {
console.warn('输入过快');
}
current = $('input').val();
}, 500);
})
}
//因为输入框没有dom的变化,所以不需要重复绑定
$('input').blur(function () {
$('#keyword-list').css('border', 'none');
$('#keyword-list').html('');
})
//渲染的逻辑
function renderKeywordList(Result) {
let content = '';
const itemStyle = `style= "line-height:50px; cursor:pointer;"`
Result.forEach(element => {
content += `<div ${itemStyle}>${element}</div>`
});
$('#keyword-list').css('border', '1px solid #ccc');
$('#keyword-list').html(content);
$('#keyword-list div').mousedown(function () {
//把输入框的值设置未点击的项
$('input').val(this.innerHTML);
$("#search").click();
//把输入框dom置空
$('#keyword-list').css('border', 'none');
$('#keyword-list').html('');
});
//鼠标移入移出事件
$('#keyword-list div').mouseenter(function () {
$(this).css('background', '#ccc');
})
$('#keyword-list div').mouseleave(function () {
$(this).css('background', '#fff');
})
}
划重点,$('#keyword-list div').mousedown()不能使用$('#keyword-list div').click()替代,因为blur事件会在click之前触发,一旦点击了下拉框中的div,会先执行blur的回调,导致值没传过去就被清空了,click事件会在mousedown和mouseup之后触发,也就是按下和松开鼠标构成一个点击事件,触发顺序mousedown>mouseup>blur>click,为啥我会知道呢
有不懂和错误的地方欢迎提问