JavaScript动态生成元素绑定事件时的一些问题、解决与思考

先上结论: 在用js给动态生成的dom元素添加事件时会遇到很多坑。

坑1:使用了 queryselectorall方法获取元素,这个方法获得的是一个静态的Nodelist伪数组,这意味着之后无论你如何改动DOM节点,它都岿然不动,这真是太坑人了T——T,可能这就是便捷的代价吧。使用getElementByTagName或者getElementByClassName就行了。

坑2:在给动态生成的dom元素绑定事件时,最好使用事件委托的方式来绑定。通过给一个静态的父级元素绑定事件,之后无论生成多少子元素都能绑上事件咯。如果不采用事件委托,那就得注意了,只能给已经存在的元素绑定事件,也就是说,绑定事件一定得在元素动态生成完成以后。这种方法通常非常复杂,并不推荐。

为什么在使用queryselectorall方法会出现这种问题呢?

我们先来看看大佬是怎么说的。

原因是:动态NodeList对象在浏览器中可以更快地被创建并返回,因为他们不需要预先获取所有的信息,而静态NodeList对象从一开始就需要取得并封装所有相关的数据。两种对象类型的创建方式是完全不同的。

DynamicNodeList(动态NodeList)对象通过在cache缓存中注册它的存在并创建。从本质上讲,创建一个新的DynamicNodeList是非常轻量级的,因为不需要做任何的前期工作。每次访问 DynamicNodeList 时, 必须查询 document 的变化, length 属性 以及 item() 方法证明了这一点

相比之下,StaticNodeList对象实例由另外一个文件创建,然后循环填充所有的数据。在document中执行静态查询的前期成本相比DynamicNodeList要显著提高很多倍。

静态NodeList 和 动态NodeList的区别 - 前端学习之路 - 前端乱炖

 通过queryselectorall方法我们获得的正是这样一个静态的NodeList对象,而通过getElementByTagName或者getElementByClassName等方法我们获得的是HTMLCollection对象,这是一个元素节点的集合,同样是动态的。下面来看看我的理解吧。

首先动态的这些就相当于一个直接指向DOM元素的指针,它所指向的就是这个DOM元素所以能实时更新,并且在创建时只需要指向这个DOM元素就好了,速度非常快。而静态的创建之前会先进行一个深拷贝,然后让这个指针指向深拷贝后的复制版DOM元素。(JavaScript里面没有内存指针什么的,这么说只是为了方便理解,大家别被我忽悠咯)

                                                                                                                                       

我与bug那些事:今天在用js写微博界面时又出现了bug,在通过js动态生成节点元素时,一开始没有通过事件委托的方式去绑定事件,导致绑定事件时出现各种问题。问题一: 绑定事件总是出现乱序,事件无法绑定到正确的位置,或者无法给所有元素绑定好事件。经测试是queryselectorall方法的问题,得到的数组是不会变的。调整后重试,发现问题依旧存在,在每次添加节点后之前给前面节点绑定的事件就会失效。如下面这个测试的js代码,当动态生成新的元素后,之前绑定的事件就失效了,querySelectorAll和getElement这两种方式都会失效。需要在元素生成后再重新给所有元素绑定事件,但过于繁琐。

let p = document.querySelectorAll("button");
let i = document.getElementsByTagName("button");
i[1].addEventListener("click", () => alert("???"))
p[0].addEventListener("click", () => alert("??"))
console.log(p);
console.log(i);
// 动态的生成一些节点
document.body.innerHTML += "<button>111</button>";
let l = document.querySelectorAll("button");
let o = document.getElementsByTagName("button");
console.log(l);
console.log(o);

 解决:想起还有事件委托这种大宝贝可以用,但是动态生成的元素比较多,且要添加的事件也比较多,用事件委托也有点麻烦,不过好算是较为简便的解决了问题。PS:之前用vue写的一份结果老师不让用,于是就用原生js再写一遍,感觉真是要被框架给惯坏了,数据驱动简直不要太方便!用js做到这种工作量就麻烦了许多,但平时基础也不能马虎了,有时间还得好好看看js。感兴趣的朋友可以加我好友噢,我是个爱好前端的小白,我们一起努力吧,今天也是与bug斗智斗勇的一天,拜拜!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值