闭包与let块级作用域实现异步节点控制
效果图:
html:
<ul>
<li>item--<a href= "javascript:;">删除</a></li>
<li>item--<a href= "javascript:;">删除</a></li>
<li>item--<a href= "javascript:;">删除</a></li>
<li>item--<a href= "javascript:;">删除</a></li>
<li>item--<a href= "javascript:;">删除</a></li>
</ul>
js:
var aNodes = document.querySelectorAll('ul > li > a');
for (var i = 0; i < aNodes.length; i++) {
aNodes[i].onclick = function(){
aNodes[i].parentNode.style.display='none';
}
}
这样写,会发现无法操作节点,因为JavaScript语言在es6之前没有块级作用域,而用户点击“删除”时,页面已经渲染完成,for也循环完成,i的值是5;所以无论点击哪一个“删除”,都是aNodes[5].parentNode.style.display='none';
此时只需要将for循环内的onclick异步操作使用闭包进行包裹,这样每次for循环,都会执行函数,形成一个私有的作用域,让每次循环的变量i能存到对应的函数作用域中,从而达到效果,具体代码如下:
var aNodes = document.querySelectorAll('ul > li > a');
for (var i = 0; i < aNodes.length; i++) {
(function(i){
aNodes[i].onclick = function(){
aNodes[i].parentNode.style.display='none';
}
})(i);
}
除此之外,也可使用es6中的let定义变量i,let自带块级作用域特性,此方法实现会更加简单,代码如下:
var aNodes = document.querySelectorAll('ul > li > a');
for (let i = 0; i < aNodes.length; i++) {
aNodes[i].onclick = function(){
aNodes[i].parentNode.style.display='none';
}
}
当然,这是为了展示闭包与块级作用域特性,实际使用事件代理会更方便:
var ul = document.querySelector('ul');
ul.addEventListener('click', function (e) {
if (e.target.localName == 'a') {
e.target.parentNode.style.display='none';
}
});
jquery事件代理:
$('ul').on('click', 'a', function () {
$(this).parent().hide();
});