公司项目有像上图中效果的功能需求这也是很常见功能很简单功能,通过一个小例子和大家聊聊js的事件冒泡和默认事件。
先说说一般的实现方式即使用阻止事件冒泡的方式去做,给input绑定一个click事件(并阻止事件冒泡到window)当点击上input的时候就显示ul再给window或者document 绑定一个click事件当点击页面其他地方的时候隐藏ul。
这里还要给ul 添加一个代理点击事件(事件代理比遍历li绑定点击事件性能要高)当点击到下面的li的时候把li里面的内容添加到input里面 并且此时ul 是不能隐藏的 要想ul不隐藏就得阻止事件冒泡防止事件传播到 window或者document上从而隐藏了ul原理跟给input阻止事件冒泡是一样的。
说说上面实现方式的不足就是给window或document添加点击事件当用户每点击一次页面的时候都会去执行一下给window绑定是函数(除了点击到input和ul 阻止了事件冒泡)具体实现代码如下。
<meta charset="UTF-8">
<title>test</title>
<style>
*{padding:0;margin:0; }
ul{ list-style: none; }
#test2{
width:170px;
}
#box{ padding:30px; }
#list{ width:170px; border:1px solid #ccc; display:none; }
#list li{ padding:5px;cursor:pointer; }
</style>
<div id="box" >
<input type="text" id="test2" >
<ul id="list" >
<li>111</li>
<li>222</li>
<li>333</li>
<li>44</li>
</ul>
</div>
<script>
var $inp = $('#test2'),
$ul = $('#list'),doc = $(document);
$inp.on('click',show);
doc.on('click',hide);
$ul.on('click','li',changeText);//事件代理性能更好
function changeText(e){
e.stopPropagation();
$inp.val($(this).text());
}
function show(e){
e.stopPropagation(); //阻止事件冒泡
$ul.show();
}
function hide(){
$ul.hide();
}
</script>
总结:
优点兼容性好ie6-ie8都ok。
缺点在window上绑定事件用户每次点击页面都会被触发绑定事件。
但我个人认为最优的实现方案不需要给window绑定click事件(用阻止默认事件的方式去实现), 我们只需给input绑定一个focus事件一个blur事件当input focus 的时候就显示ul,当input blur 的时候 就隐藏 ul 在给ul 绑定一个mousedown事件(阻止游览器默认事件)。注意:这里有必要说明一下事件的执行顺序和为什么不能给ul添加点击事件。当点击ul的时候鼠标键上升的时候 mousedown 执行完了input才会失去焦点blur。 mousedown --> blur 如果直接给ul 添加click事件input 会在失去焦点了blur 才会触发ul的click事件 事件执行顺序 blur --> click 当input blur了ul就隐藏了故得不到自己想要的效果。
按照我的方案基于第一种方案的代码稍加改动就可以具体实现的代码如下:
test
<style>
*{padding:0;margin:0; }
ul{ list-style: none; }
#test2{
width:170px;
}
#box{ padding:30px; }
#list{ width:170px; border:1px solid #ccc; display:none; }
#list li{ padding:5px;cursor:pointer; }
</style>
- 111
- 222
- 333
- 44
var $inp = $('#test2'),
$ul = $('#list');
$inp.on('focus',show);
$inp.on('blur',hide);
$ul.on('mousedown','li',changeText);//事件代理性能更好 把mousedown改成click 可以验证我上面说的事件执行顺序感兴趣的自己动手试下。
function changeText(e){
e.preventDefault(); //把阻止事件冒泡改成阻止默认事件
$inp.val($(this).text());
}
function show(e){
$ul.show();
}
function hide(){
$ul.hide();
}
</script>
ie8下的效果图
ie9下的效果
在ie9及以上都ok没什么问题 但是ie8下跟我们想要的效果就不一样了每次点击ul会自动去隐藏了也就是说在ie8下 ul的mousedown是被执行了但是他没有去阻止掉input blur事件让input失去了焦点触发了绑定在blur事件的函数从而隐藏了ul。
总结:
优点不需要在window上绑定事件少一次事件绑定。
缺点兼容性ie9及以上不兼容ie8(有小问题)。