前言
今天接到一个需求,类似 Google 搜索根据关键字自动联想功能,如下图所示
首先说一下我的实现思路
- 监听搜索框的值改变事件,获取关键字,请求数据接口,显示结果列表面板
- 监听搜索结果列表点击事件,获取当前值,同时隐藏结果列表面板
- 监听搜索框失去焦点事件,隐藏结果列表面板(这一步主要是考虑到用户可能会没有点击结果列表,直接搜索)
问题描述
在实现第 3 步的时候遇到了一个问题,当我的点击搜索结果列表的时候搜索框的值并没有发生变化。
review 了一遍代码发现,是因为点击搜索结果列表的时候,先触发了搜索框失去焦点事件,所以结果面板先被隐藏了,所以我在点击的时候其实并没有点击到,也就不会触发结果列表点击事件。
下面贴一下问题代码(因为是公司内部项目,所以这段代码是我为了模拟写的测试代码)
html 结构
<style type="text/css">
ul,li{
list-style: none;
margin: 0 0;
padding: 0 0;
}
.search-block{
position: absolute;
border-radius: 0 2px 2px 0;
border: 1px solid #c3c3c3;
min-width: 171px;
background-color: #ffffff;
z-index: 999;
display: none;
}
.search-block:hover{
z-index: 1000;
}
.search-block li:hover{
background-color: #c3c3c3;
}
</style>
搜索:<input name="keyword" placeholder="请输入关键字" />
<div class="search-block">
<ul>
<li>测试11111111111111</li>
<li>测试22222222222222</li>
<li>测试33333333333333</li>
</ul>
</div>
JS 代码
<script type="text/javascript">
// 搜索框值发生改变事件
$("input[name=keyword]").on('input', function(){
$('.search-block').css('left', $(this).offset().left);
$('.search-block').css('top', $(this).offset().top + 20);
$('.search-block').show();
});
// 搜索框失去焦点隐藏搜索结果
$("input[name=keyword]").on('blur', function(){
$('.search-block').hide();
})
// 点击搜索结果条触发事件
$(".search-block li").on('click', function(){
var val = $(this).text();
console.log(val);
$('input[name=keyword]').val(val);
$('.search-block').hide();
})
</script>
问题演示
解决思路
既然问题出在搜索框失去焦点的时候,那么判断搜索框失去焦点的时候当前鼠标所在的位置不就好啦,只有鼠标不在搜索结果面板的时候才隐藏。
最开始想到的实现方案是先获取结果面板的区域,然后再拿到鼠标位置的坐标,判断是否在结果区域内,但是这种方法实现起来太过复杂,不利于后期阅读和维护。所以暂时放弃了
于是我想到了第二种方法,使用鼠标移入选择器 :hover, 设置搜索结果面板鼠标移入的样式,css 新增以下代码
.search-block:hover{
z-index: 1000;
}
同时在搜索框失去焦点事件里判断 z-index 不等于 1000 时才隐藏结果面板
// 输入框失去焦点隐藏搜索结果
$("input[name=keyword]").on('blur', function(){
if($('.search-block').css('z-index') != 1000){ // 新增判断
$('.search-block').hide();
}
})
这个时候就是正常的效果了
大佬们有更好的解决办法欢迎指教o( ̄▽ ̄)ブ