input和label之间不为人知的秘密

1,695 阅读3分钟

label标签嵌套input标签的问题

首先说一下问题,问题出在点击事件click上,当label标签嵌套input标签时,label下的其他元素标签无论与input是何种布局,点击其他元素都会执行input的默认事件以及手动添加的事件。现在的需求是点击其他元素不让触发input的默认事件以及手动添加的事件。

 <div>
    <label>
        <div style="width: 40px;height: 40px;background: red;"
            class="con1"
            onclick="openInfo('我的部门')">
        </div>
        <p class="con2">北京单车有限公司-临时组</p>
        <div>
            <input
                class="con3" 
                type="checkbox"
                onclick="addSearchPass('周本东')">
        </div>
    </label>
</div>
<script>
    function addSearchPass(val) {
        console.log(val)
    }
    function openInfo(val) {
        console.log(val);
    }
</script>

预想结果:这段代码很简单,点con1打印出 “我的部门”,点con3打印出 “周本东”并改变复选框状态,点con2没有反应,他的元素没有添加事件

结果

当点击con1时打印出了“我的部门”和“周本东”,并且改变了复选框状态,点击con2打印了“周本东”并改变了复选框状态,点击con3打印了“周本东”并改变了复选框状态。

分析

一、为何con1和con2能执行con3的默认事件以及添加的事件,难道是事件冒泡导致,于是乎我便在addSearchPass事件加了阻止事件冒泡stopPropagation():

 <script>
    function addSearchPass(val) {
        event.stopPropagation();
        console.log(val)
    }
    function openInfo(val) {
        console.log(val);
    }
</script>

结果还是不行,失败了;

二、点击con1时通过打印顺序可以看出,先执行的openInfo事件,那么让这个事件return false是否可以阻止addSearchPass触发呢:

<script>
    function addSearchPass(val) {
        event.stopPropagation();
        console.log(val)
    }
    function openInfo(val) {
        console.log(val);
        return false;
    }
</script>

还是失败;

三、是不是checkbox的input事件本身的问题,于是乎跟换了input的type

这些input试了个遍,除了hidden(元素都没了,肯定不行),还是不行,照样会执行input的默认事件以及添加的事件。

进入正轨

百度了一堆,也没找到解决办法,在放弃了通过js解决后,怀疑是不是html的结构问题,然后发现是label这货和input之间居然勾勾搭搭,label和表单控件有一层显示和隐式的关系,于是乎我便将包裹它们的label标签去了试试,果然正常了,一切都恢复到我们想要的样子了。

<div>
    <div style="width: 40px;height: 40px;background: #red;"
        class="con1"
        onclick="openInfo('我的部门')">
    </div>
    <span class="con2">北京单车有限公司-临时组</span>
    <div>
        <input 
            class="con3" 
            type="checkbox"
            onclick="addSearchPass('周本东')">
    </div>
</div>
<script>
    function addSearchPass(val) {
        console.log(val)
    }
    function openInfo(val) {
        console.log(val);
    }
</script>

可是我就想要label里面嵌套input还不让他俩勾勾搭搭的咋整?

解决方案:

 <div>
    <label>
        <label>
            <div style="width: 40px;height: 40px;background: #aaa;"
                class="con1"
                onclick="openInfo('我的部门')">
            </div>
            <span class="con2">北京单车有限公司-临时组</span>
        </label>
        <div>
            <input class="con3" 
                type="checkbox"
                onclick="addSearchPass('周本东')">
        </div>
    </label>
</div>
<script>
    function addSearchPass(val) {
        console.log(val)
    }
    function openInfo(val) {
        console.log(val);
    }
</script>

最后通过在其他元素外再嵌套一层label标签就可以隔绝label和input之间这种不良反应。

总结

此次的问题算是找到了一种解决方案,并没有深究label和input的这种勾勾搭搭的行为,他俩的秘密有感兴趣的可以去细品一番,也许能品出另一番风味来,希望大家能多多找出这种喜欢勾搭的元素来,也欢迎大家评论留言,可以提出其他的解决办法或者想法,让我们大家能互相勾搭勾搭。。。