通常在为了使用户体验更好,在一些复选框或单选框和输入框中,会使用label包裹input这样用户只需点击后面文字,即可选中当前项。
代码结构如下
<ul
class="table-main "
@mouseenter.stop="myMouseenter(index)"
:class="{'table-main-active':mouseIndex==index?true:false, 'table-main-actived':selectIndexArr.indexOf(index)!=-1?true:false}"
v-for="(detail,index) in details"
@click.stop="getIndex($event,index)">
<!-- 只给ul绑点击事件点击li标签时只会触发li上的点击事件 点击label会触发label和input上的点击事件 -->
<li class="w-sm fl">
<!-- 只给input绑点击事件只会触发input上的点击事件 -->
<input type="checkbox" v-model="selectIndexArr" :value="index" class="select" :id="`mycheck${index}`" />
<!-- 只给label绑点击事件只会触发label上的点击事件 -->
<label :for="`mycheck${index}`"></label>
</li>
<li class="w-sm fl">
{{index+1}}
</li>
</ul>
页面显示如下
当我点击li时能勾选上但是点击label时就勾选不上。然后打印发现点击label时触发了两次事件,很疑惑,明明只有一个点击事件。
原因:是使用label和input点击时会触发默认行为,会分别触发label和input上的点击事件导致勾选不上。
解决:label与其绑定元素的关系,当点击label时,浏览器会自动给被绑定元素也执行点击事件的行为,试了下用e.preventDefault(),发现果然阻止了这个默认行为。事件也就只被执行一次了。也可是判断是哪个标签上的事件如果是label上的事件就不继续执行,即只执行了一次
getIndex(e,index) {
// if (e.target.tagName === 'LABEL') return // 因为原生click事件会执行两次,第一次在label标签上,第二次在input标签上,故此处理
// e.preventDefault() // 阻止默认事件
let that = this;
if (that.selectIndexArr.indexOf(index) == -1) {
that.selectIndexArr.push(index);
} else {
that.selectIndexArr.splice(that.selectIndexArr.indexOf(index), 1);
}
},
在vue中可以直接使用.prevent修饰符阻止默认事件,而不用去上面代码一样去e.preventDefault()或if (e.target.tagName === ‘LABEL’) return
@click.stop.prevent="getIndex($event,index)"