做一个微博发布的功能,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循环是怎么做的呢?
//未看到全部源代码的旧答案
1.先回答第一个
你尝试吧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中;
此部分不会被执行,直到你点击删除按钮(触发onclick);
可以查一查回调函数的概念和函数执行顺序的相关知识。