click事件执行两次这么皮??

问题描述

在项目中遇到一个小bug——label标签上绑定了一个返回一层路由的点击事件,然而每次点击都会返回两层!!

经调试发现,label标签中包裹input,而事件绑定在label标签中时,点击label区域,事件会执行两次。

问题测试

<label onclick="labelConsole()">
  <input type="checkbox" onclick="inputConsole()">勾选协议
</label>
复制代码
function labelConsole (){
  console.log('label_click 这是我们想要的操作')
}
function inputConsole (){
  console.log('input_click')
}
复制代码
  1. 点击label区域(不直接点击input区域):label上的事件被触发执行一次,同时子元素input本身也绑定有click事件,触发后又冒泡传递给label,又触发了一次label绑定事件。

  1. 直接点击input区域:触发input绑定事件后又冒泡传递给label,触发了label的绑定事件。

分析原因

  1. 元素默认绑定click事件

一些元素如<a><button><input>本身就默认绑定了click事件,即使你不绑定,click事件发生时他们也会接收到。

  1. label标签的扩展性

它把所包含的input的用户交互区域扩展了,注意的是label和所包含的input都开始绑定默认事件,此时会发生事件冒泡现象。在label上的click事件的处理函数会触发2次就是由于:第一次是label自己接收到事件,执行处理函数,第二次是input接受到事件后冒泡传递给label,再次触发处理函数。

解决方案

方案1:将原绑定于label的事件,直接绑定于input上。

<label>
  <input type="checkbox" onclick="labelConsole()">勾选协议
</label>
复制代码

此时,当点击label区域或者直接点击input区域,由于checkbox本身有默认click监听器,所以会触发一次我们绑定的事件。

方案2:阻止事件冒泡

<label onclick="labelConsole()">
  <input type="checkbox" onclick="inputConsole()">勾选协议
</label>
复制代码
function labelConsole (){
  console.log('label_click 这是我们想要的操作')
}
function inputConsole (){
  console.log('input_click');
  window.event? window.event.cancelBubble = true : e.stopPropagation();
}
复制代码

点击labelinput区域的时候效果如上,这种方法看似实现了我们的需求,只让我们想要的操作触发一次,但是如果你直接点击的是input,那就跪了。

没错,当你直接点击input的时候只会触发input的绑定事件,而我们绑定在label上的事件则无人问津。这并不符合预期,所以方案2不太可取,最后采取方案1。

猜你喜欢

转载自juejin.im/post/5c66752d6fb9a049d37fa191