javascript - js事件委托
黄舟
黄舟 2017-04-11 11:44:30
[JavaScript讨论组]
    
  • 1
  • 2
  • 3

上面这样可以把事件绑定在ul上,通过dataset来判断点击的是哪个li,来触发不同的动作

下面这种

  • 1

  • 2

  • 3

li 内有多个子元素,点击 li 必然可能会点到子元素,如果子元素上不写dataset等标记,如何判断点了哪个li? 如果给li的子元素都写上标记那肯定不对吧,太多了。这种情况怎么优化事件绑定的过程?

黄舟
黄舟

人生最曼妙的风景,竟是内心的淡定与从容!

全部回复(5)
天蓬老师

事件被触发的时候,事件对象event有两个很关键属性Event.targetEvent.currentTarget
它们俩的主要区别就在于,currentTarget该属性总是指向被绑定事件的元素,而target则是指向触发该事件的元素。

举个例子,你把这个事件绑定在了最上级的<ul>标签中,然后你现在点击了下属某个<span>标签。
之后就是事件冒泡,冒泡至<ul>标签时,回调被触发,此时Event.currentTarget指向的是当前<ul>的DOM对象,而Event.target则是指向你点击的那个<span>的DOM对象。

所以在事件委托的处理中,只要在回调中对Event.target进行分析,就能知道触发事件的元素是不是你需要的了。

天蓬老师

一个思路是,遍历父元素找到<li>

var target = e.target
while( target ){
    if( target.nodeName == 'li' ){
        return
    }
    target = target.parentNode
} 

// 读取标记
target.dataIndex
大家讲道理

你要是想获取序号,根本不用标注,直接从ul的子节点一个一个往下找就可以了。如果只有几个或十几个li,不会很慢。

<ul>
<li><span>1st</span></li>
<li><span>2nd</span></li>
<li><span>3rd</span></li>
</ul>

<script>

    document.addEventListener('DOMContentLoaded', function() {

        var ul = document.querySelector('ul');
        ul.addEventListener('click', function(e) {
            // <span>, <ul>
            console.log(e.target, e.currentTarget);
           
            var li = e.target;
            while(li.nodeName !== 'LI')
                li = li.parentNode;
            
            var idx = [].indexOf.call(ul.children, li) + 1;
            console.log(idx);
        });
    })

</script>
天蓬老师

建议看下DOM事件流程,即:

捕获阶段→目标阶段→冒泡阶段

其中捕获阶段就是事件从父元素向子元素传递的过程,说白了就是父元素应该比子元素更早的拿到事件,所以我觉得题主可以直接在每个li元素上直接挂事件监听、然后设置捕获模式(addEventListener第三个参数设置为true),这样处理时再判断下index就行了。
另外,我觉得不用特别纠结在事件委托上,个人以为它更加适用于父元素里有大量重复的子元素或者父元素内的子元素不确定的情况。

PHP中文网

CSS

li > * { pointer-events: none; }

这是另一种解决方案

热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号