最近在看 JS 性能优化方面,说到了 createDocumentFragment()方法,对该方法有印象,但为了进一步了解,我还是重新查阅一遍,顺便把 DOM 操作也给总结一下。
创建新节点
- createDocumentFragment()方法
该方法是用来创建一个虚拟的节点对象,或者说,是用来创建文档碎片节点。它可以包含各种类型的节点,在创建之初是空的。
DocumentFragment 不是真实 DOM 树的一部分,它的变化不会触发 DOM 树的重新渲染,且不会导致性能等问题。
当把一个 DocumentFragment 节点插入文档树时,插入的不是 DocumentFragment 自身,而是它的所有子孙节点,即插入的是括号里的节点。这个特性使得 DocumentFragment 成了占位符,暂时存放那些一次插入文档的节点。
- createElement()方法
在 HTML 文档中,document.createElement() 方法用于创建一个由标签名称 tagName 指定的 HTML 元素
来看一个例子, 对于页面已存在的<ul id="ul"></ul>
元素,我们想往里面添加 li 标签
1 | var ul = document.getElementById('ul') |
上面操作看起来很正常,但实际要很多的插入操作和改动;而每一次的插入都会引起重新渲染,该操作会引发多次渲染,在性能优化方面,有一点是减少 DOM 操作,因为 DOM 操作导致了页面的重绘或重排。
- createDocumentFragment()方法和 createElement()方法区别
如果是用 createDocumentFragment()方法操作
1 | var ul = document.getElementById('ul') |
相比 createElement()方法,这次是先将这些元素添加到 fragment 中,再统一将 fragment 添加到页面,会减少页面渲染 dom 的次数,效率会明显提升。因为 fragment 文档片段存在于内存中,并不在 DOM 中,所以将子元素插入到文档片段中时不会引起页面回流(新创建的 fragment 片段在文档内是没有对应的标签的,这里添加的是片段的所有子节点)
- createTextNode()方法
该方法会创建一个文本节点。
HTML 元素通常是由元素节点和文本节点组成。创建一个标题 (h1), 你必须创建 “h1” 元素和文本节点:
1 | var h = document.createElement('h1') |
DOM 更改:添加、移除、替换、插入
1 | // 添加、删除子元素 |
前面三个用法就一目了然,对于 insertBefore()方法来举个例子:
1 | <ul id="ul"> |
1 | var newEle = document.createElement('li') |
页面输出:
1 | insertNode |
DOM 查询
元素查询的 API 返回的的结果是 DOM 节点或者 DOM 节点的列表
1 | getElementById() |
querySelector() 方法返回匹配指定 CSS 选择器元素的第一个子元素, 该方法只返回匹配指定选择器的第一个元素。如果要返回所有匹配元素,需要使用 querySelectorAll() 方法替代.
1 | document.querySelector("#test"); // 获取到id名为test的首个元素 |
- querySelector 系列方法与 getElementBy 系列方法对比
- 得到的元素不是需要很麻烦的多次 getElementBy..的话,尽量使用 getElementBy 系列方法,因为 getElementBy 系列执行速度更快。
- 得到的元素需要很麻烦的多次 getElementBy…组合才能得到的话使用 querySelector,方便。
- querySelector()选择的标签是静态的,也就是说在选中之后,能够一直保存,也就是脱离了被选择的成为副本。而 getelementsBy 系列方法是动态的,相互映射,在调用时,变化可以及时的反映在页面上。
1 | // 用 querySelector 操作元素 |
1 | var ul = document.getElementsByTagName('ul')[0] |
- 还有元素的 DOM 导航方法:
1 | // 获取父元素、父节点 |
属性操作
1 | getAttribute(key) |