为什么两个事件嵌套在一起才有效?分开写就不执行了吗?

做一个微博发布的功能,textarea输入内容,点击发布btn,就新增一个子节点li(包括输入的文字和删除按钮dels);点击删除,可以删除评论。

思路:为了实现,点击哪个btn就把哪一行的li节点删掉:用一个for循环,遍历所有的btn,然后删除。

代码如下:

var dels = document.getElementsByTagName("button");//定义一个dels,获取所有的删除按钮

 
 btn.onclick = function(){  
    var li = document.createElement("li");      //点击btn会添加一个li,包含文字和删除的button标签
    li.innerHTML = txt+"<button>删除</button>"  //txt是用户输入的内容
    
    //……此处省略添加细节
    
    //重点是下面。实现点击删除按钮dels,就删除掉整个li(包含在ul中).
    //先遍历,再移除
     for(var j=0;j<dels.length;j++){
             dels[j].onclick = function()
            {
              ul.removeChild(this.parentNode);
             }
    
}

问题来了,上面写的代码是可以实现的。但是删除事件dels是在点击发布组btn.onclick事件中的,回头想想,发布事件和删除事件,是两个不相干的时间,理论上不是一个包含在一个里面,所以我把删除事件的for循环移到了btn.onclick事件的外面。如下:

btn.onclick = function(){  
 
    //……此处省略添加细节
  
}

//唯一的区别,是把删除的for循环移到了btn.onclick事件的外面
for(var j=0;j<dels.length;j++)
{
   dels[j].onclick = function()
     {
      ul.removeChild(this.parentNode);
      }
 }
    

结果,程序就没有执行删除事件了,dels按钮没有用了。

正确的源代码在这里,经过测试了的,请点击这里

总结:
求助大神2个问题:
1、发布事件btn.onclik和删除dels.onclick理论上是不同的时间,为什么我dels拿出来就不执行了。 //事实证明,好像是第二个for循环中j就执行了一次就再也不执行了,但是为什么放在btn中就还执行?

2、假设按照第一种的写法,dels事件在btn事件中,程序是怎么执行的呢?比如:先btn,发布一个,生成一个li和del,但del的onclick没有点击,for循环j也没执行;接着我再多生成几个li,一直没有去删除(触发dels.onclick),我过了很久再去点dels,他马上就执行了,那for循环是怎么做的呢?

阅读 4.2k
2 个回答

//未看到全部源代码的旧答案
1.先回答第一个

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
    </head>
    <ul id='ul'>
    <li><button>1</button></li>
    <li><button>2</button></li>
    <li><button>3</button></li>
    <li><button>4</button></li>
    <li><button>5</button></li>
    </ul>
    <body>
    </body>
    <script>
    var ul = document.getElementById('ul')
    var btns = document.getElementsByTagName('button');
        for(var j=0;j<btns.length;j++)
        {
               btns[j].onclick = function()
         {
          console.log(this);
          }
 }
//        ul.innerHTML+='<li><button>new</button></li>'
    </script>
</html>

你尝试吧js的最后一行打开关上看看差别,我觉得是btns在dom树改变后不是原来的btns了,因为使用innerHTML会覆盖掉之前的<button>,ul内的内容已经整体被覆盖了。虽然btns还在但,在ul内的btns已经被覆盖掉了,成了全新的。所以响应事件就不在了。
而使用
相关可以看看这个HTMLCollection的动态特性,当然我也是猜测。

//补充
for循环所在的环境不被重新执行的话,for循环是只遍历一遍的。
appendChild的方法可以保留原有btns的响应事件,同时需给新添加的btn重新绑定。
2.第二问
事件(onclick)后的函数叫回调函数。只有事件触发才会被执行。
点击发布后(1)生成li(2)添加li (3)执行for循环
(3)注意:添加li后修改了dom结构,浏览器自动将新的button加入了dels中;

function()
        {
         ul.removeChild(this.parentNode);
         }

此部分不会被执行,直到你点击删除按钮(触发onclick);
可以查一查回调函数的概念和函数执行顺序的相关知识。

目前只能看出来新增元素不去刻意绑定事件它是不会自动绑上去的,能否贴一段精简后并且经测试的代码?

推荐问题
宣传栏