网站
Document: createElement() 方法 | MDN
Element: insertAdjacentHTML() 方法 | MDN
引入
有时候页面初始结构不够用,需要根据用户操作或数据动态添加新元素,也可能需要删除不需要的元素。
JS 提供了创建、插入和删除 DOM 节点的方法,让页面结构可以在运行时改变。
正文
定义
定义
创建和删除元素是用 JS 动态地向页面中添加新的 DOM 节点,或者从页面中移除已有的 DOM 节点。
创建元素
使用 document.createElement() 创建一个新的元素节点。
const div = document.createElement("div");这里只是在内存中创建了一个 <div> 元素对象,还没有放到页面上,所以用户看不到。
创建后通常会设置内容或属性,再插入到页面中。
const li = document.createElement("li");
li.textContent = "新内容";
li.className = "item";插入元素
创建好的元素需要插入到 DOM 树中,页面上才会显示。
parent.appendChild()
把元素添加为父元素的最后一个子元素。
<ul id="list">
<li>HTML</li>
<li>CSS</li>
</ul>const list = document.querySelector("#list");
const newItem = document.createElement("li");
newItem.textContent = "JS";
list.appendChild(newItem);执行后 <ul> 末尾多了一个 <li>JS</li>。
parent.insertBefore()
把元素插入到指定元素之前。
<ul id="list">
<li>HTML</li>
<li>CSS</li>
<li>JS</li>
</ul>const list = document.querySelector("#list");
const items = document.querySelectorAll("li");
const newItem = document.createElement("li");
newItem.textContent = "SVG";
list.insertBefore(newItem, items[2]);"SVG" 会插入到 "JS" 之前。
insertAdjacentHTML()
不需要先创建元素,可以直接插入 HTML 字符串。
<ul id="list">
<li>HTML</li>
</ul>const list = document.querySelector("#list");
list.insertAdjacentHTML("beforeend", "<li>CSS</li>");
list.insertAdjacentHTML("afterbegin", "<li>SVG</li>");| 位置参数 | 插入位置 |
|---|---|
"beforebegin" | 元素自身之前 |
"afterbegin" | 元素内部的第一个子元素之前 |
"beforeend" | 元素内部的最后一个子元素之后 |
"afterend" | 元素自身之后 |
insertAdjacentHTML() 写起来很方便,适合快速插入一小段 HTML。
删除元素
element.remove()
直接调用元素自身的 remove() 方法即可删除。
<p id="tip">提示信息</p>const tip = document.querySelector("#tip");
tip.remove();页面上的 <p> 元素会被移除。
parent.removeChild()
通过父元素删除指定的子元素。
<ul id="list">
<li>HTML</li>
<li>CSS</li>
<li>JS</li>
</ul>const list = document.querySelector("#list");
const items = document.querySelectorAll("li");
list.removeChild(items[1]);第二个 <li> (CSS)会被删除。
removeChild() 需要拿到父元素才能调用,remove() 则不需要。
| 方法 | 调用方式 | 特点 |
|---|---|---|
element.remove() | 元素自身调用 | 不需要知道父元素 |
parent.removeChild(child) | 父元素调用 | 需要知道父元素和子元素 |
例子
动态添加列表项
<input id="input" type="text" placeholder="输入内容">
<button id="addBtn">添加</button>
<ul id="list"></ul>const input = document.querySelector("#input");
const addBtn = document.querySelector("#addBtn");
const list = document.querySelector("#list");
addBtn.addEventListener("click", function () {
if (input.value === "") {
return;
}
const li = document.createElement("li");
li.textContent = input.value;
list.appendChild(li);
input.value = "";
});输入文字点击按钮,会在列表中新增一项。
删除列表项
<ul id="list">
<li>HTML <button class="del">删除</button></li>
<li>CSS <button class="del">删除</button></li>
<li>JS <button class="del">删除</button></li>
</ul>const list = document.querySelector("#list");
list.addEventListener("click", function (event) {
if (event.target.classList.contains("del")) {
event.target.parentElement.remove();
}
});点击某一项的”删除”按钮,整个 <li> 会从页面中移除。
这里用了事件委托,把点击事件绑在 <ul> 上,这样即使动态添加新的 <li> 也能正常工作。
动态添加和删除结合
<input id="input" type="text" placeholder="输入待办">
<button id="addBtn">添加</button>
<ul id="list"></ul>const input = document.querySelector("#input");
const addBtn = document.querySelector("#addBtn");
const list = document.querySelector("#list");
addBtn.addEventListener("click", function () {
if (input.value === "") {
return;
}
const li = document.createElement("li");
const span = document.createElement("span");
span.textContent = input.value;
const delBtn = document.createElement("button");
delBtn.textContent = "删除";
delBtn.className = "del";
li.appendChild(span);
li.appendChild(delBtn);
list.appendChild(li);
input.value = "";
});
list.addEventListener("click", function (event) {
if (event.target.classList.contains("del")) {
event.target.parentElement.remove();
}
});这是一个简单的待办列表,可以添加项目,也可以点击删除按钮移除项目。
批量插入与 DocumentFragment
如果要一次插入很多元素,每次都 appendChild() 会导致浏览器反复重绘页面,影响性能。
document.createDocumentFragment() 创建一个临时的”文档片段”,先把所有元素添加到片段中,再一次性插入页面。
<ul id="list"></ul>const list = document.querySelector("#list");
const fragment = document.createDocumentFragment();
for (let i = 1; i <= 100; i++) {
const li = document.createElement("li");
li.textContent = "项目 " + i;
fragment.appendChild(li);
}
list.appendChild(fragment);浏览器只会重绘一次,而不是 100 次。
| 方式 | 性能 | 适用场景 |
|---|---|---|
多次 appendChild() | 每次插入都重绘 | 少量元素 |
insertAdjacentHTML() | 一次解析 HTML 字符串 | 快速插入 HTML 片段 |
DocumentFragment | 最后只重绘一次 | 大量元素批量插入 |
特点
document.createElement()在内存中创建元素,不会自动显示在页面上- 创建后需要用
appendChild()或insertBefore()插入到 DOM 中 element.remove()直接移除元素,不需要知道父元素parent.removeChild()通过父元素删除子元素insertAdjacentHTML()可以直接插入 HTML 字符串,写法简洁DocumentFragment适合批量插入,减少页面重绘次数- 动态创建的元素一样可以绑定事件、修改样式
注意事项
- 创建元素后如果不插入 DOM,元素只存在于内存中
- 频繁操作 DOM 会影响性能,批量操作尽量用
DocumentFragment insertAdjacentHTML()和innerHTML一样有 XSS 风险,不要直接插入用户输入的内容- 删除元素后,如果有变量引用它,变量不会自动变成
null,需要手动处理 - 动态添加的元素如果需要事件监听,推荐用事件委托
理解
可以把 DOM 想象成一棵拼插玩具树。
createElement() 是在工厂里做好一个新零件。
appendChild() 和 insertBefore() 是把零件安装到树的指定位置。
remove() 和 removeChild() 是把零件从树上拆下来。
我理解创建和删除元素的重点是:先创建,再配置,最后插入。掌握这三步就可以动态改变页面结构。
引出
掌握了创建和删除元素之后,页面结构就可以动态变化了。接下来学习 JS 事件,让页面能够响应用户的操作。