问题描述:
demo大概模样: 搜索框中输入关键字, 下方弹出提示, 点击提示词条, 去往相应的词条页面(这里用alert代替); 而搜索框失去焦点时, 会隐藏下方的提示内容
代码如下:
<body>
<div class="container">
<input type="text" id="input" placeholder="输入关键字" />
<ul class="test" id="test">
<li><a href="javascript:void(0)">西瓜</a></li>
<li><a href="javascript:void(0)">苹果</a></li>
<li><a href="javascript:void(0)">橙子</a></li>
<li><a href="javascript:void(0)">甘蔗</a></li>
<li><a href="javascript:void(0)">地瓜</a></li>
<li><a href="javascript:void(0)">土豆</a></li>
<li><a href="javascript:void(0)">山药</a></li>
<li><a href="javascript:void(0)">葛根</a></li>
</ul>
</div>
<script>
var test = document.getElementById('test');
var input = document.getElementById('input');
var links = document.getElementsByTagName('a');
input.onfocus = function () {
test.style.display = 'block';
}
input.onblur = function () {
test.style.display = 'none';
}
for (var i = 0; i < links.length; i++) {
links[i].onclick = function() {
alert(i); // do something
}
}
</script>
</body>
点击词条, 并没有运行alert, 提示内容倒是隐藏了
原因分析:
搜索框的blur事件在a链接的click事件之前执行了, 结果是a链接的click事件压根没有触发
解决方案:
1. 首先想到的是延迟搜索框blur事件的执行
<body>
<div class="container">
<input type="text" id="input" placeholder="输入关键字" />
<ul class="test" id="test">
<li><a href="javascript:void(0)">西瓜</a></li>
<li><a href="javascript:void(0)">苹果</a></li>
<li><a href="javascript:void(0)">橙子</a></li>
<li><a href="javascript:void(0)">甘蔗</a></li>
<li><a href="javascript:void(0)">地瓜</a></li>
<li><a href="javascript:void(0)">土豆</a></li>
<li><a href="javascript:void(0)">山药</a></li>
<li><a href="javascript:void(0)">葛根</a></li>
</ul>
</div>
<script>
var test = document.getElementById('test');
var input = document.getElementById('input');
var links = document.getElementsByTagName('a');
input.onfocus = function () {
test.style.display = 'block';
}
input.onblur = function () {
setTimeout(() => {
test.style.display = 'none';
}, 100);
}
for (var i = 0; i < links.length; i++) {
links[i].onclick = function() {
alert(i); // do something
}
}
</script>
</body>
这时看起来好像可以了, 但是有个问题, 一旦a链接的点击事件运行时间超过搜索框的blur事件的延迟时间, 比如这里设置的100ms, 就又不行了。 当然你可以设置延时长一点, 但如果场景要求不能延迟太长怎么办?
2. 将a链接的click事件, 换成mousedown事件
<body>
<div class="container">
<input type="text" id="input" placeholder="输入关键字" />
<ul class="test" id="test">
<li><a href="javascript:void(0)">西瓜</a></li>
<li><a href="javascript:void(0)">苹果</a></li>
<li><a href="javascript:void(0)">橙子</a></li>
<li><a href="javascript:void(0)">甘蔗</a></li>
<li><a href="javascript:void(0)">地瓜</a></li>
<li><a href="javascript:void(0)">土豆</a></li>
<li><a href="javascript:void(0)">山药</a></li>
<li><a href="javascript:void(0)">葛根</a></li>
</ul>
</div>
<script>
var test = document.getElementById('test');
var input = document.getElementById('input');
var links = document.getElementsByTagName('a');
input.onfocus = function () {
test.style.display = 'block';
}
input.onblur = function () {
test.style.display = 'none';
}
for (var i = 0; i < links.length; i++) {
links[i].onmousedown = function() {
alert(i); // do something
}
}
</script>
</body>
因为blur事件的执行时机晚于mousedown, 所以可以愉快的alert了, 但是也还是有问题, 右键点击a链接, 也会执行mousedown, 当然, 如果你不介意右键行为, 可以就此打住了。但是如果场景要求在a链接上方右键时, 可以显示“在新标签页中打开链接”,像下面这样, 又该怎么办?
3.触发mousedown时, 判断是鼠标左键还是右键,左键则正常执行,右键时, 需要在blur事件执行前打断
<body>
<div class="container">
<input type="text" id="input" placeholder="输入关键字" />
<ul class="test" id="test">
<li><a href="javascript:void(0)">西瓜</a></li>
<li><a href="javascript:void(0)">苹果</a></li>
<li><a href="javascript:void(0)">橙子</a></li>
<li><a href="javascript:void(0)">甘蔗</a></li>
<li><a href="javascript:void(0)">地瓜</a></li>
<li><a href="javascript:void(0)">土豆</a></li>
<li><a href="javascript:void(0)">山药</a></li>
<li><a href="javascript:void(0)">葛根</a></li>
</ul>
</div>
<script>
var test = document.getElementById('test');
var input = document.getElementById('input');
var links = document.getElementsByTagName('a');
input.onfocus = function () {
test.style.display = 'block';
}
input.onblur = function () {
test.style.display = 'none';
}
for (var i = 0; i < links.length; i++) {
links[i].onmousedown = function(e) {
e = e || window.event;
if (e.button === 0 || e.button === 1) { // 鼠标左键(ie8及以下button为1)
alert(i); // do something
} else if (e.button === 2) { // 鼠标右键
if (e.preventDefault) {
e.preventDefault();
}
}
}
}
</script>
</body>
ok了, 这下在chrome浏览器中可以正常运行, 但是, 在ie8及以下, 右键时, 提示内容还是会隐藏, 无法达到预期的效果, 原因可能是 Event 对象的 cancelable 属性是 fasle, 没有默认动作,或者说不能阻止默认动作。