基本DOM 操作
作者:©endless
1、Dom 介绍
Dom 表示由多层节点构成的文档 例如下面的 HTML 文档
<html>
<head>
<title>Sample Page</title>
</head>
<body>
<p>Hello World!</p>
</body>
</html>
其文档结构如下图所示:
所以对于 dom 树的操作实际上是对各个节点的操作。
所有节点继承自node类型,其共有12个类型,常用的主要有以下几个类型:
| 常量 | 值 | 描述 |
|---|---|---|
Node.ELEMENT_NODE | 1 | 元素节点、例如 <div>、<p> |
Node.TEXT_NODE | 3 | Element中的实际文字 |
Node.COMMENT_NODE | 8 | Comment节点,表示注释 |
Node.DOCUMENT_NODE | 9 | 文档,在浏览器中表示页面 |
Node.DOCUMENT_FRAGMENT_NODE | 11 | 轻量文档,在上面的 Dom 操作不会触发重绘 |
其余的节点类型可以自行查阅 MDN
2、Dom 操作
1、节点关系
NodeList
每个节点都有一个 childNodes 属性,其中包含一个 NodeList 的实例。NodeList 是一个类数组 对象,用于存储可以按位置存取的有序节点。
注意:Dom 结构的变化会自动反应在
NodeList中
假设有如下文档结构:
<body>
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
</body>
获取到 body 下的NodeList:
let childList = document.body.childNodes;
// NodeList(5) [div, div, div, div, text]
// 有 text 节点,说明 childNodes 会把所有节点查询出来
给 body添加一个节点:
let div = document.createElement('div');
div.textContent='5';
document.body.appendChild(div);
这时来打印一下 childList:
console.log(childList);
// NodeList(6) [div, div, div, div, text, div]
// 可以看出来 childList 会根据 dom 结构实时变化
相关 API
属性
firstChild: 第一个子节点
lastChild: 最后一个子节点
previousSibling: 前一个兄弟节点
nextSibling: 后一个兄弟节点
parentNode: 父节点
方法
hasChildNodes(): 返回 true 说明节点有一个或多个子节点
2、操作节点
appendChild(): 在 childNodes末尾添加节点,如果是已经存在的节点,会转移到新的位置
insertBefore(): 插入指定位置,接收两个参数:要插入的节点和参照节点,参照节点为null时,插入最后
replaceChild(): 替换节点,接收两个参数:要插入的节点和要替换的节点
removeChild(): 移除节点
clone(): 复制节点,传 true 为深拷贝,会包含复制节点和整个子dom树,false为浅拷贝,只包含复制节点
3、定位节点
getElementById(): 通过 id 获取节点
getElementsByTagName(): 通过标签名获取,返回的是HTMLCollection
4、获取属性
getAttribute(): 获得对应属性
setAttribute(): 设置对应属性
removeAttribute(): 移除对应属性
5、创建节点
createElement(): 创建新元素
3、Dom 扩展
1、Selectors API
querySelector(): 返回匹配该模式的第一个后代元素
querySelectorAll(): 返回所有匹配的节点,返回一个NodeList静态实例
matches(): 如果元素匹配css选择符返回 true,否则返回 false。
2、元素遍历
这几个 API 跟上面类似,但不会再包含文本和注释了。
childElementCount、firstElementChild、lastElementChild、previousElementSibling、nextElementSibling
3、H5 新出的一些方法
getElementsByClassName(): 返回对应类名元素的NodeList
classList: 包含 4 个方法
-
add(): 向类名列表中添加指定的字符串值 value。如果这个值已经存在,则什么也不做 -
contains(): 返回布尔值,表示给定的 value 是否存在 -
remove(): 从类名列表中删除指定的字符串值 value -
toggle(): 如果类名列表中已经存在指定的 value,则删除;如果不存在,则添加
innerHTML: 插入标记
outerHTML:返回字符串,写入时,会替代调用它的元素
children: 返回只包含元素的 Element 类型的子节点
4、example
下面通过一个例子来对 Dom 操作的 API 进行练习,练习中会尽量把所有 API 都用进去。
对于一个初始的HTML文档
// index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Dom 操作练习</title>
</head>
<body>
</body>
</html>
首先引入script和style
// index.html
<body>
<script>
let link = document.createElement('link');
link.rel = "stylesheet";
link.type = "text/css";
link.href = "./index.css"
document.head.appendChild(link);
let script = document.createElement('script');
script.src = "./index.js";
document.body.appendChild(script);
</script>
</body>
这时的HTML文档如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Dom 操作练习</title>
<link rel="stylesheet" type="text/css" href="./index.css">
</head>
<body>
<script>...</script>
<script src="./index.js"></script>
</body>
</html>
然后将导入script和style的代码去掉
// index.js
document.body.removeChild(
document.body.querySelector('script')
)
在body中插入一个div
let div = document.createElement('div');
div.appendChild(document.createTextNode('a temp div'));
document.body.insertBefore(
div,
document.body.getElementsByTagName('script')[0]
)
将插入的div替换掉,这里使用 innerHTML和outerHTML:
innerHTML方式:
let tempDiv = document.body.querySelector('div');
tempDiv.innerHTML = `
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
`;
outerHTML方式:
tempDiv.outerHTML = `
<div>
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
</div>
`;
为每个div添加样式并设置id
// 最外层的 div 添加 container 类
document.body.children[0].classList.add('container');
// 内层 div 每个都添加 box 类
let nodeList = document.querySelector('div.container').children;
let len = document.querySelector('div.container').childElementCount;
for(let i = 0; i < len; ++i) {
nodeList[i].classList.add('box');
nodeList[i].setAttribute('id', i+1);
}
删除 id为box3的节点
document.querySelector('div.container').removeChild(
document.body.querySelector("#box4").previousElementSibling
)
最后:
熟能生巧、多看文档、多练习