如何在jQuery按钮内嵌入文本框,点击文本框不触发按钮事件
解决按钮内输入框触发按钮点击事件的问题
问题背景
你当前的代码运行正常,但存在一个小问题:点击按钮内部的数字输入框时,会意外触发按钮的点击事件。你希望保留输入框嵌入按钮的设计,同时按钮可能是动态创建的,想找到适配这种场景的解决方案。
你的代码如下:
<!DOCTYPE html> <html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <title>Title</title> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <meta name="robots" content="noindex, nofollow"> <meta name="googlebot" content="noindex, nofollow"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css"> <script src="https://code.jquery.com/jquery-1.11.1.min.js"></script> <script src="https://code.jquery.com/ui/1.11.1/jquery-ui.min.js"></script> <script> $(document).ready(function () { $('#countButton').on("click", function(){ target=$('#until').prop("value"); tl=(""+target).length; numberString=""; for(var i=0; i<=target; i++){ numberString+=((""+i).padStart(tl, '0'))+"<br />"; } $("#numbers").html(numberString); }); }); </script> </head> <body> <button class="ui-button ui-widget ui-corner-all" id="countButton"> Count from 0 to <label for="until"> <input id="until" value="20" style="width: 50px;" type="number" min="1" /> </label>! </button> <div id="numbers"></div> </body> </html>
解决方案
问题的核心是事件冒泡:点击输入框时,事件会向上传递到父元素按钮,最终触发按钮的点击逻辑。我们可以通过两种方式解决,同时兼容动态创建按钮的场景:
方法一:阻止输入框的事件冒泡
给输入框绑定点击事件,直接阻止事件向上传递。因为按钮可能动态创建,我们用事件委托的方式绑定:
$(document).ready(function () { // 用事件委托绑定按钮点击事件,兼容动态创建的按钮 $(document).on("click", '#countButton', function(){ let target = $('#until').prop("value"); let tl = (""+target).length; let numberString = ""; for(let i=0; i<=target; i++){ numberString += ((""+i).padStart(tl, '0'))+"<br />"; } $("#numbers").html(numberString); }); // 阻止输入框的点击事件冒泡到按钮 $(document).on("click", '#until', function(e){ e.stopPropagation(); }); });
这样点击输入框时,事件不会传递到按钮,自然就不会触发按钮的点击逻辑了。
方法二:在按钮事件中判断触发源
在按钮的点击回调里,判断事件的触发元素是不是输入框或其标签,如果是就直接终止逻辑:
$(document).ready(function () { $(document).on("click", '#countButton', function(e){ // 若点击的是输入框或关联标签,直接返回不执行后续逻辑 if($(e.target).is('#until') || $(e.target).is('label[for="until"]')){ return; } let target = $('#until').prop("value"); let tl = (""+target).length; let numberString = ""; for(let i=0; i<=target; i++){ numberString += ((""+i).padStart(tl, '0'))+"<br />"; } $("#numbers").html(numberString); }); });
这种方法不需要额外绑定输入框事件,直接在按钮回调内做判断,同样能达到预期效果。
补充说明
- 事件委托(
$(document).on(...))是为了适配动态创建的按钮,不管按钮何时被添加到页面,事件都能正常生效。 - 两种方法都能保留你想要的输入框嵌入按钮的设计,可根据个人代码习惯选择。
内容的提问来源于stack exchange,提问作者Lukas Schmidinger
相关产品推荐
相关产品推荐

