给列表元素添加点击事件

如下html代码,如何给一个列表中所有子元素添加点击事件,输出对应内容?

<ul id="container">
    <li id="li1">1</li>
    <li id="li2">2</li>
    <li id="li3">3</li>
    <li id="li4">4</li>
    <li id="li5">5</li>
</ul>

首先,循环列表,依次添加点击事件:

for(var i = 1; i < 5; i++){
    document.getElementById('li' + i).addEventListener('click', function() {
        alert(i);
    })
}

似乎很容易理解这段代码,但是实际上,不管点击哪个<li>标签,都会弹出数字5。还不清楚原因的同学,可以先来了解一下html事件处理程序和js作用域的相关知识。

有个很直接的方法,每次输出li标签对应的innerText即可。如果我一定要输出这个i呢?可以使用闭包的方式:

for(var i = 1; i < 5; i++){
    (function(x){
        document.getElementById('li' + x).addEventListener('click', function(){
            alert(x)
        })
    })(i)
}

这里形如(function(){})()的代码块,叫做“立即被调用的函数表达式”(Immediately Invoked Function Expression)。可以思考,这里闭包如何产生?

另外,采用ES6新增的变量类型let,也可以快速的解决该问题。

for(let i = 1; i < 5; i++){
    document.getElementById('li' + i).addEventListener('click', function() {
        alert(i);
    })
}

用let代替var来声明变量,就可以把变量的作用域限制在当前代码块中。变量i只存在于for循环中,一旦循环结束,在其他位置均无法访问该变量。

上面方法都是通过循环,通过addEventListener方法分别给每个<li>标签添加点击事件。这样做完全OK,不会导致什么问题。

但是在javaScript中,添加到页面上的事件处理程序的数量,将直接关系到页面的整体运行性能。首先,每个函数都是对象,都会占用内存;内存中的对象越多,性能就越差。其次,必须事先制定所有事件处理程序而导致的DOM访问次数,会延迟整个页面的交互就绪时间。

想象以上示例中,<li>标签的数量很大时,循环为每个子元素添加事件,绝非好方法。下面给出一种优雅的方法,采用事件委托

document.getElementById('container').addEventListener('click', function(event) {
    var target = event.target;
    if(target.tagName == 'LI'){
        alert(target.innerText);
    }
}, false);

这段代码里,使用事件委托只为<ul>元素添加一个onclick事件处理程序。因为有事件冒泡机制,单击每个<li>标签时,都会被这个函数处理。关于事件流,主要为事件捕获阶段与事件冒泡阶段,可以另行了解。

参阅学习文档:

You Don't Know JS — 第三章:作用域与闭包

ECMAScript 6 入门 — let 和 const 命令

转载于:https://www.cnblogs.com/aliyuntao/p/7737812.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值