点击父元素触发子元素click事件的实现及问题解决
解决点击父元素触发子元素委托click事件的问题
我来帮你分析下原来的代码为啥没生效,以及怎么搞定这个需求:
问题出在哪?
你用$('body').on('click', '.child', doSomething)绑定的是事件委托,这种逻辑是靠事件从.child冒泡到body时才会触发的。而你原来用的triggerHandler('click')有两个致命问题:
- 它不会触发事件冒泡,
body上的委托监听器根本捕获不到这个“内部触发”的事件; - 如果用户直接点击
.child本身,你的代码会重复触发一次doSomething,导致逻辑执行两次。
修复后的代码
把triggerHandler换成trigger,同时加个判断避免重复触发,代码如下:
$('.parent').on('click', function(e) { // 只有点击的不是.child本身时,才触发子元素的click事件 if (!$(e.target).is('.child')) { $(this).find('.child').trigger('click'); } // 如果你不需要阻止父元素点击的默认行为,可以删掉下面这行 // e.preventDefault(); });
为啥这个方案能行?
trigger('click')会触发完整的事件流,包括事件冒泡,这样body上的委托监听器就能正常捕获到.child的click事件,从而执行doSomething;- 加了
!$(e.target).is('.child')的判断,当用户直接点击.child时,不会重复触发,避免逻辑重复执行。
另一种思路(如果能直接访问doSomething)
如果doSomething是你能直接调用的命名函数,也可以跳过事件触发,直接在父元素的click事件里调用它,同时传递模拟的事件对象,保证函数能正常获取事件相关属性:
$('.parent').on('click', function(e) { const $child = $(this).find('.child'); // 创建一个模拟的click事件对象,和真实点击.child时的事件一致 const simulateEvent = $.Event('click', { target: $child[0], currentTarget: $child[0] }); // 调用doSomething,同时把this指向.child元素 doSomething.call($child[0], simulateEvent); });
这种方法不需要依赖事件冒泡,但前提是你能直接拿到doSomething函数,如果它是匿名函数的话就不适用了。
内容的提问来源于stack exchange,提问作者Sometip
相关产品推荐
相关产品推荐

