即使元素在鼠标按下和鼠标向上之间从光标下方移动,如何处理"click"事件?



我有一个<input>和一个<button>

输入有一个onblur事件处理程序,(有时)会导致<button>被移动;如果将焦点放在<input>上,用户去单击<button>(因此在单击完成之前它从指针下方移动),他们当前必须将指针移动到按钮的新位置并再次单击它。 这种体验是次优的。

我希望用户只需单击<button>一次(但必须保留<input>失去焦点时按钮移动的功能)。 但是,如果用户在鼠标悬停之前将鼠标悬停在按钮上,然后将鼠标指针移开(包括从应用程序切换焦点),则不应触发任何单击事件(正常情况)。

我看不到任何基于处理onmousedown和/或onmouseup的方法在某些边缘情况下不容易出错。 我所能想到的就是在onblur处理程序中强行移动光标,以便单击完成(如果确实会?——但这可能也是一个糟糕的用户体验。

如何最好地处理这个问题?

$('button').click(
$('<li><input></li>')
.children('input')
.blur(function(){
if (!this.value.length)
this.parentElement.remove();
})
.end(),
function(e){
e.data.clone(true)
.appendTo($(this).data('target'))
.children('input')
.focus();
}
);
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
List 1<button data-target="#list1">+</button><ul id="list1"></ul>
List 2<button data-target="#list2">+</button><ul id="list2"></ul>

一种方法是在一秒钟而不是立即淡出元素的过程中淡出元素,这让用户有时间在按钮移动之前完成单击:

$(this.parentElement).fadeOut("slow", function() {
$(this).remove();
});

现场示例:

$('button').click(
$('<li><input></li>')
.children('input')
.blur(function(){
if (!this.value.length)
$(this.parentElement).fadeOut("slow", function() {
$(this).remove();
});
})
.end(),
function(e){
e.data.clone(true)
.appendTo($(this).data('target'))
.children('input')
.focus();
}
);
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
List 1<button data-target="#list1">+</button><ul id="list1"></ul>
List 2<button data-target="#list2">+</button><ul id="list2"></ul>

也就是说,我想我会尝试找到一种方法,使列表元素之间的空间根本不改变,因为这仍然意味着事情会移动,只是在不同的时间 -希望在某个时候用户不会受到它的困扰,但是......不过,在这种情况下很棘手,因为列表彼此 重叠——第二个列表会在某个时候移动。如果您总是有一个输入框供用户输入,那么第二个列表将在不同的时间移动(当框中确实有一个值并且您为下一个值添加新的空白值时)。可以使用固定的列表大小和滚动来完成,但这取决于整体设计。

我有一个相关的问题,即我正在设置按钮样式以在按下时缩小,使用:active伪类在鼠标按下时调整按钮大小,并在按钮获得焦点时重置其大小:focus伪类。但是,如果单击按钮足够靠近其边缘,它仍会被激活并缩小,但光标现在刚好在按钮的边界之外,并且按钮将不再获得焦点。

这是点击事件本身工作方式的结果。对于要在给定element上触发onclick事件,光标必须"在[光标]位于元素内部时同时按下和释放"。 但是,如果光标在释放之前移动到元素之外,则会在包含这两个元素的"最具体的祖先元素"上触发该事件。具体而言,这会导致在element上触发mousedown事件,在其ancestor element上触发mouseup事件。

因此,解决方案是监视按钮的mousedown事件,并在触发其父级mouseup事件时单击该按钮(即,光标被按下在按钮上,但在其父级上释放)。

香草JS代码:

// The CSS selector for the buttons to monitor
const selectors = "button";
window.addEventListener('DOMContentLoaded', () => {
document.querySelectorAll(selectors).forEach(button => {
// Watch for button press
button.addEventListener('mousedown', event => {
// The button is the event's original target
const element = event.target;

// Click if the cursor is released over the button's parent
element.parentElement.addEventListener('mouseup', () => {
element.click();
}, { once: true });
});
});
});

如果按钮的父级大小与按钮的大小相同(例如使用width: fit-content),则此方法效果最佳。否则,如果光标释放在远离按钮的位置,但仍位于按钮的父元素上,则可能会发生意外单击。

最新更新