我有以下文件:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta charset="UTF-8">
<title>Test</title>
<script src="https://code.jquery.com/jquery-2.1.1.js"></script>
</head>
<body>
<div id="alert"></div>
<input type="text" id="input"></br>
<span id="span">Span</span>
<script>
$(function() {
$('#input').on('change', function() {
console.log('change');
$('#alert').append('<div>An alert</div>');
});
$('#span').on('click', function() {
console.log('click');
});
});
</script>
</body>
</html>
单击span并运行click事件处理程序。
更改输入并更改事件处理程序。
更改输入并单击跨度(不保留输入 - 例如没有标签输出,也没有单击其他位置)并且更改事件处理程序运行但单击事件处理程序不运行。
如果我从更改事件处理程序中删除了append,然后更改输入并单击span,两个事件处理程序都会运行,因此append会以某种方式干扰click事件。
如何在更改事件处理程序附加元素后触发click事件?
这是引发问题的最小代码。在实际情况中,有多个输入,并且跨度的样式看起来和行为就像一个按钮。输入上的更改事件处理程序验证值,如果它们无效则添加警报。通常,输入在不单击范围/按钮的情况下进行更改,但编辑输入然后单击范围/按钮,同时输入焦点仍在输入上,在这种情况下,我希望两个事件处理程序都能运行。
在进一步调查中,我发现问题在于如何生成事件。
每个DOM Level-2:点击元素上的指针设备按钮时发生click事件。单击被定义为同一屏幕位置上的mousedown和mouseup。这些事件的顺序是:
mousedown
mouseup
click
如果没有更改事件处理程序中的'append',当我编辑输入时,请点击我看到的范围:
但是,通过更改事件处理程序中的追加,我看到:
在后一种情况下,mousedown和mouseup事件具有相同的坐标(如果我小心点击时不移动鼠标):它们都是span元素边界内和输入元素外部的坐标。尽管如此,在Firefox和Chrome中,mouseup与input元素而不是span元素相关联。
所以,我的问题变成:为什么mouseup事件与input元素而不是span元素相关联,当它的坐标在span元素的边界内而不在input元素的边界内时?
答案 0 :(得分:2)
可以通过多种方法来解决此问题。这完全取决于UI演示。根据设计,您还可以考虑其他解决方法。截至目前,我可以想到可以解决这个问题的三件事:
将警报div设置为高度并使其可垂直滚动。这样做会阻止您的跨度位置变化,并会触发这两个事件。 e.g
<div id="alert" style="height: 100px; overflow-y: scroll;"></div>
或者您可以稍微更改您的JavaScript以满足您的目的。以下是代码片段(已修改评论),其中包含更改以满足您的需求。
$(function() {
var isMouseDownOnSpan = 0; // flag variable added to track whether user clicked on the span.
$('#input').on('change', function() {
console.log('change');
$('#alert').append('<div>An alert</div>');
// If user tries to click on the span then trigger the click event manually.
if(isMouseDownOnSpan){
$('#span').trigger('click');
}
});
// Bind mousedown event and set the flag value true. This ensures that the user clicked on the span.
$('#span').on('mousedown', function(e) {
isMouseDownOnSpan = 1;
});
$('#span').on('click', function() {
isMouseDownOnSpan = 0; // Reset flag value once the click event is fired.
console.log('click');
});
});
或者上述任何一个都不适合你,那么你可以设计你的跨度并给它一定的宽度和高度,这样即使在追加警告div后,用户的鼠标也在跨度边界内。我知道这不是一个永久的解决方案,但它仍然可以最大限度地减少现实生活场景中的错误变化。 ;)
答案 1 :(得分:0)
我保存了您的代码并在浏览器中运行并且可以正常运行。为什么你认为它没有?你在检查控制台输出吗?
答案 2 :(得分:0)
在您的更改事件处理程序中添加$('#span')。click()
$(function() {
$('#input').on('change', function() {
console.log('change');
$('#alert').append('<div>An alert</div>');
$('#span').click();
});
$('#span').on('click', function() {
console.log('click');
});
});
答案 3 :(得分:0)
我弄清楚我的问题是什么:
当我添加到div时,文档布局会发生变化。我将光标放在跨度上并按下鼠标左键。这会导致输入失去焦点,从而触发更改事件。 change事件处理程序将一个div附加到#alert div。这会将屏幕下方的所有内容推到屏幕下方。然后我释放了鼠标按钮,没有移动它。但是鼠标不再超出范围 - 由于布局已更改,现在它已经在输入上,因此mouseup事件将输入作为其目标,而不是跨度。
即使鼠标没有移动,屏幕布局也发生了变化,因此鼠标离开了跨度并输入了输入。跨度看到没有鼠标的mousedown,所以没有点击。输入看到没有mousedown的mouseup,所以也没有点击那里。
我的错误是认为因为我没有移动鼠标,所以鼠标仍然应该超出范围。
如果我在跨度之后放置警报div,那么编辑输入并单击跨度按预期工作,但这不是我想要的屏幕布局。
我想如果我将警报div留在顶部,我需要在更改事件处理程序中执行的操作是将消息添加到警报div,这会将范围向下移动,然后将鼠标向下移动以使其保持静止在跨度。然后,当用户释放鼠标按钮时,它仍然会跨越跨度,跨度可能(我希望)接收到点击事件。
答案 4 :(得分:-2)
$(function() { $('#input').on('change', function() { console.log('change'); $('#alert').append('An alert', function(){ $('#span').on('click', function() { console.log('click'); }); }); }); $('#span').on('click', function() { console.log('click'); }); });