创建节点
createElement()
:::info 该用法用于创建元素节点 :::
var div = document.createElement("div"); // 创建DOM对象后,放在堆内存当中
div.innerHTML = "123";
document.body.appendChild(div);
createTextNode()
:::info 该方法用于创建文本节点 :::
var text = document.createTextNode("这是创建的文本节点");
document.body.appendChild(text);
createComment()
:::info 该方法用于创建注释节点 :::
var comment = document.createComment("这是创建的注释节点");
document.body.appendChild(comment);
createDocumentFragment()
:::info
该方法用于创建一个「文档片段」fragment
是一个指向空DocumentFragment
对象的引用,该对象不在DOM
节点中,就是一个临时的容器,所以操作的时候不会频繁的引起页面回流
:::
来看个案例:
现在我有1000
个数据我想添加到ul
下面
<body>
<ul id="list"></ul>
</body>
var oUl = document.getElementById("list");
for (let i = 0; i < 1000; i++) {
var oLi = document.createElement("li");
oLi.innerHTML = "这是第" + i + "个项目";
oLi.className = "list-item";
oUl.appendChild(oLi); // 循环循环,重复的回流
}
但是这样动态的操作ul
会引起页面重复的回流,那我们可以创建一个空的div
,该空div
没有在节点树当中,最后把所有的元素添加到空div
后再把内容赋值给ul
var oUl = document.getElementById("list");
var oDiv = document.createElement("div");
for (let i = 0; i < 1000; i++) {
var oLi = document.createElement("li");
oLi.innerHTML = "这是第" + i + "个项目";
oLi.className = "list-item";
oDiv.appendChild(oLi);
}
oUl.appendChild(oDiv);
但是此时还是不太理想,因为多了个div
元素。
那么我们就可以创建一个fragment
对象来替换div
var oUl = document.getElementById("list");
// var oDiv = document.createElement("div");
var oFrag = document.createDocumentFragment("div");
for (let i = 0; i < 1000; i++) {
var oLi = document.createElement("li");
oLi.innerHTML = "这是第" + i + "个项目";
oLi.className = "list-item";
// oDiv.appendChild(oLi);
oFrag.appendChild(oLi);
}
// oUl.appendChild(oDiv);
oUl.appendChild(oFrag);
因为文档片段存在于内存中,并不在DOM树中,所以将子元素插入到文档片段时不会引起页面回流(对元素位置和几何上的计算)。因此,使用文档片段通常会带来更好的性能。
增加节点
appendChild()
:::info 该方法用于父节点将子节点插入到父节点最后 :::
var div = document.getElementsByTagName("div")[0];
var p = document.createElement("p");
p.innerHTML = "创建的P标签";
var text = document.createTextNode("创建的文本节点");
var comment = document.createComment("创建的注释节点");
div.appendChild(p);
div.appendChild(text);
div.appendChild(comment);
appendChild()
还可以「剪切」节点。
<body>
<a href=""></a>
<div></div>
</body>
var a = document.getElementsByTagName("a")[0];
var div = document.getElementsByTagName("div")[0];
div.appendChild(a);
insertBefore()
:::info 该方法用于父节点将子节点插入到某个子节点之前 :::
<body>
<div>
<p></p>
</div>
</body>
var div = document.getElementsByTagName("div")[0];
var p = document.getElementsByTagName("p")[0];
var a = document.createElement("a");
div.insertBefore(a, p);
var h1 = document.createElement("h1");
h1.innerHTML = "创建的H1";
div.insertBefore(h1, a);
删除节点
removeChild()
:::info
该方法用于父节点将子节点从父节点中删除
📌 该方法删除子节点后只是从DOM
文档结构中删除,但无法从内存当中删除
:::
var div = document.getElementsByTagName("div")[0];
var p = document.getElementsByTagName("p")[0];
div.removeChild(p);
remove()
:::info
该方法用于节点将自己删除
📌 该方法是真正的删除,会从内存中删除
:::
var p = document.getElementsByTagName("p")[0];
p.remove();
其他方法
replaceChild()
:::info 该方法用于把新节点替换旧节点 :::
var div = document.getElementsByTagName("div")[0];
var h1 = document.getElementsByTagName("h1")[0];
var h2 = document.createElement("h2");
div.replaceChild(h2, h1);
cloneNode()
:::info
复制节点及其整个子 DOM 树。
接收一个布尔值参数,表示是否深复制。在传入true
参数时,会进行深复制,如果传入false
,则只会复制调用该方法的节点。
:::
var oP = document.getElementsByTagName("p")[0];
var newP = oP.cloneNode(); // 只克隆 p 节点
var newP = oP.cloneNode(true); // 克隆 p 节点和底下的内容
文档写入
write()
:::info 该方法接收一个字符串参数,可以将这个字符串写入网页中。 :::
<html>
<head>
<title>document.write() Example</title>
</head>
<body>
<p>
The current date and time is:
<script type="text/javascript">
document.write("<strong>" + (new Date()).toString() + "</strong>");
</script>
</p>
</body>
</html>
如果是在页面加载完之后再调用**document.write()**
,则输出的内容会重写整个页面。
插入值
innerHTML
:::info
该属性访问的时候返回元素下所有的节点内容
在写入时会根据提供的字符串值以新的DOM
子节点替代元素中原来包含的所有节点。
:::
<body>
<div>
<h1></h1>
</div>
</body>
var div = document.getElementsByTagName("div")[0];
console.log(div.innerHTML); // <h1></h1>
div.innerHTML = "123";
console.log(div.innerHTML); // 123
div.innerHTML += "456";
console.log(div.innerHTML); // 123456
案例 🌰 :
<body>
<div>
<ul id="list"></ul>
</div>
</body>
var list = document.getElementById("list");
var data = [
{
title: "天下无贼",
area: "中国🇨🇳",
},
{
title: "复仇者联盟",
area: "美国🇺🇸",
},
{
title: "千与千寻",
area: "日本🇯🇵",
},
];
data.forEach((item, index) => {
list.innerHTML += `<li>${item.title}--${item.area}</li>`;
});
innerText
:::info
该属性在读取的时候会返回节点下所有的文本节点
在用于写入值时,innerText
会移除元素的所有后代并插入一个包含该值的文本节点,包括标签字符串。
:::
<body>
<div>
文本节点1
<p>
文本节点2
<span>文本节点3
<a href="">文本节点4</a>
</span>
</p>
</div>
</body>
var div = document.getElementsByTagName("div")[0];
console.log(div.innerText)
插入标签字符串:
div.innerText = "<a>a标签内容</a>"
操作元素的属性
setAttribute()
:::info 该方法可以设置元素的属性 :::
var div = document.getElementsByTagName("div")[0];
div.setAttribute("id", "box");
getAttribute()
:::info 该方法用于获取元素的属性 :::
console.log(div.getAttribute("id")); // box
HTML5
版本后给元素新增了规范,自定义应该以data-*
开头
div.setAttribute("data-name", "aixiaoye");
div.setAttribute("data-age", "18");
// 这样设置自定义属性后,可以用 dataset 属性访问到
// dataset 管理了自定义属性,必须是 data- 开头
console.log(div.dataset);
// DOMStringMap {name: 'aixiaoye', age: '18'}
removeAttribute()
:::info 用于从元素中删除属性。这样不单单是清除属性的值,而是会把整个属性完全从元素中去掉。 :::
div.removeAttribute("class");