闭包与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();
});
posted @ 2020-11-13 13:21  是明啊  阅读(125)  评论(0编辑  收藏  举报