在如今各种框架大行其道的今天,由于虚拟DOM的应用,直接手动操作DOM已经越来越少。一方面是API相对麻烦,一方面直接操作对性能也不利。但是原生JS作为“内功”的一部分,还是要了解的。
这里有一道面试题(现在应该很少见了),用JS在页面添加一千个按钮,要求点击按钮弹出对应的编号。
比较直接的方式就是,用一个for循环,用appendChild的API不断往容器里面添加按钮。这样就会有前端一个大忌——频繁修改DOM。
这里我们可以 document.createDocumentFragment()创建一个文档片段,将按钮都添加进这个文档片段里,最后再将文档片段添加进容器,文档片段被其所有的子元素所代替。
let app = document.querySelector('#app') //页面上的容器
let fragment = document.createDocumentFragment() //文档片段
let button = null
for(let i = 0; i < 1000; i++) {
button = document.createElement('button')
button.onclick = function(){alert(i+1)}
button.appendChild(document.createTextNode(`item${i+1}`))
fragment.appendChild(button)
}
app.appendChild(fragment)
这样即使添加一万个按钮,也不会造成明显的卡顿。但是这样绑定事件的方式在实际中式不被推荐的,太多元素绑定了事件,最好是在父元素上以事件代理的方式代理事件。