DOM
- DOM是 document 用来表示文档中对象的标准模型
- 它是由节点和对象组成的结构集合
- 在浏览器解析HTML标签时,会构建一个DOM树结构
- 文档对象模型(DOM)是HTML和XML 文档的编程接口
- 它提供了对文档的结构化的表述,并定义了一种方式可以使从程序中对该结构进行访问,从而改变文档的结构,样式和内容
- 任何 HTML 或XL 文档都可以用 DOM 表示为一个由节点构成的层级结构
- 节点分很多类型,每种类型对应着文档中不同的信息和(或)标记,也都有自己不同的特性、数据和方法,而且与其他类型有某种关系
下述结构中,div、p就是元素节点
,content 就是文本节点
,title 就是属性节点
css
<div>
<p title="title">
content
</p >
</div>
常见的DOM操作
日常前端开发,我们都离不开 DOM 操作。在以前,我们使用 Jquery、zepto等库来操作DOM,之后在 vue,Angular、React 等框架出现后,我们通过操作数据来控制 DOM(绝大多数时候),越来越少的去直接操作 DOM。但这并不代表原生操作不重要。相反,DOM 操作才能有助于我们理解框架深层的内容 下面就来分析 DOM 常见的操作,主要分为:
创建节点
1、document.createElement("标签名")
创建新元素
ini
const divEl = document.createElement("div")
2、document.createTextNode("content")
创建文本节点
ini
const textEl = document.createTextNode("content")
3、document.createDocumentFragment()
创建文档碎片(一个虚拟的节点对象)
ini
var ul = document.getElementById("ul");
var fragment = document.createDocumentFragment();
for (var i = 0; i < 20; i++) {
var li = document.createElement("li");
li.innerHTML = "index: " + i;
fragment.appendChild(li);
}
ul.appendChild(fragment);
4、document.createAttriute("属性名")
创建属性节点,可以是自定义属性
ini
const dataAttribute = document.createAttribute('custom')
添加节点
1、node.innerHtml
2、node.appendChild
把一个子节点添加到父节点的最后
xml
<!-- HTML结构-->
<p id="js">JavaScript</p >
<div id="list">
<p id="java">Java</p >
<p id="python">Python</p >
<p id="scheme">Scheme</p >
</div>
<!-- HTML结构-->
const js = document.getElementById('js')
js.innerHtml = "JavaScript"
const list = document.getElementById('list');
list.appendChild(js);
<!-- HTML结构变成以下-->
<div id="list">
<p id="java">Java</p >
<p id="python">Python</p >
<p id="scheme">Scheme</p >
<p id="js">JavaScript</p > <!--插入的元素-->
</div>
上述代码中,我们是获取 DOM 元素后再进行添加操作,这个 js 节点是已经存在当前文档树中,因此这个节点首先会从原先的位置删除
,再插入到新的位置 如果动态添加新的节点,则先创建一个新的节点,然后插入到指定的位置
3、node.insertBefore
插入到某元素之前
scss
parentElement.insertBefore(newElement, referenceElement)
4、node.setAttribute
在指定元素中添加一个属性节点,若属性已有则改变属性的值。
javascript
const div = document.getElementById('id')
div.setAttribute('class', 'white') // 第一个参数为属性名 第二个参数为属性值
查询节点
1、document.querySelector("css选择器")
选中单个(首个)DOM元素,若页面中没有则返回null
dart
document.querySelector('.element')
document.querySelector('#element')
document.querySelector('div')
document.querySelector('[name="username"]')
document.querySelector('div + p > span')
2、document.querySelectAll("css选择器")
返回一个包含节点子树内所有与之相匹配的 Element 节点列表,如果没有相匹配的,则返回[]
ini
const notLive = document.querySelectorAll("p");
3、ducument.getElementById("id属性值")
4、document.getElementsByClassName("className属性值")
5、document.getElementsByTagName("标签名")
6、document.getElementsByName("name属性值")
7、document.documentElement获取页面中的html标签
8、document.body
9、document.all[''] 获取页面中所有的元素节点的对象集合
10、node.parentNode 获取元素节点的父节点
11、node.parentElement //元素节点的父元素节点(一般与Node节点相同)
node.firstChild //属性的第一个节点
node.lastChild //属性的最后一个节点
node.nextSibling //节点元素后的兄弟元素(包括回车,空格,换行)
node.nextElementSibling //节点元素后的兄弟元素节点
node.previousSibling //获取元素的上一个兄弟节点(元素,文本,注释)
node.previousElementSibling //获取元素的上一个兄弟节点(只包含元素节点)
node.childNodes //元素节点的子节点(空格,换行默认为文本节点)
node.children //返回当前元素的所有元素节点
node.nodeValue //获取节点值
node.nodeName //获取节点名字
node.attributes //元素节点的属性节点
更新节点
1、node.innerHtml
即可以修改一个DOM 节点的文本内容,还可以直接通过 HTML 片段修改DOM 节点内部的子树
ini
// 获取p
var p = document.getElementById('p')
// 设置文本abc:
p.innerHtml = 'ABC' // <p id="p">ABC</p >
// 设置HTML:
p.innerHtml = 'ABC <span style="color:red">RED</span> XYZ';
2、node.innerText、node.textContent
- 自动把内容转换为字符串,保证无法设置任何html标签
- 两者的区别在于读取属性时,innerText 不返回隐藏元素的文本,而 textcontent 返回所有文本
ini
// 获取p
var p = document.getElementById('p-id');
// 设置文本
p.innerText = '<script>alert("Hi")</script>';
// <p id="p-id"><script>alert("Hi")</script></p >
3、node.style
DOM 节点的style 属性对应所有的 CSS,可以直接获取或设置。遇到 一需要转化为驼峰命名
ini
const p = document.getElementById('p-id');
p.style.color = '#ff0000';
p.style.fontSize = '20px'; // 转为驼峰命名
p.style.paddingTop = '2em';
删除节点
node.removeChild
删除一个节点,首先要获得该节点本身以及它的父节点,然后,调用父节点的 removeChild 把自己删掉
scss
// 拿到待删除节点:
const self = document.getElementById('to-be-removed");
//拿到父节点:
cost parent = self.parentElement;
//删除:
const removed = parent.removeChild(self):
removed === self; // true
删除后的节点虽然不在文档树中了,但其实它还在内存中,可以随时再次被添加到别的位置
常用的api
-
node.offset 系列 经常用于获得元素位置 offsetLeft offsetTop
-
node.client 经常用于获取元素大小 clientWidth clientHeight
-
node.scroll 经常用于获取滚动距离 scrollTop scrollLeft
offset写法 | 含义 |
---|---|
offsetParent | 返回该元素带有定位的父级元素,如果父级没有定位,则返回 body |
offsetTop | 返回元素相对于其定位父元素上方的偏移量 |
offsetLeft | 返回元素相对于其定位父元素左方的偏移量 |
offsetWidth | 返回自身包括 padding 、边框 和内容区的宽度(包括滚动条宽度) ,返回数值不带单位 |
offsetHeight | 返回自身包括 padding、边框和内容区的高度,返回数值不带单位 |
offset 与 style 的区别:
offset 系列
- 可以获取任意样式表(行内样式表、内部样式表等)中的样式值。
- 获得的数值没有单位。
- offsetWidth 等属性是只读属性,只能获取不能赋值。
- 若要获取元素大小和位置,使用 offset 系列更为合适。
style 系列
- 只能获取行内样式表中的样式值。
- style.width 获得的是带有单位的字符串。
- style.width 是可读写属性,既可以获取也可以赋值。
- 若要给元素更改样式值,则需要使用 style 进行改变。
client写法 | 含义 |
---|---|
clientTop | 返回元素上边框的宽度 |
clientLeft | 返回元素左边框的宽度 |
clientWidth | 返回自身包括 padding 和内容区的宽度,不含边框,返回数值不带单位 |
clientHeight | 返回自身包括 padding 和内容区的高度,不含边框,返回数值不带单位 |
scroll写法 | 含义 |
---|---|
scrollTop | 返回元素内容被卷去的上侧距离,返回数值不带单位 |
scrollLeft | 返回元素内容被卷去的左侧距离,返回数值不带单位 |
scrollWidth | 返回元素自身实际内容的宽度+ padding,不含边框,返回数值不带单位 |
scrollHeight | 返回元素自身实际内容的高度,不含边框,返回数值不带单位 |
三大系列大小对比
- offsetWidth:返回自身包括
padding
、边框
和内容区的宽度(包括滚动条)
,返回数值不带单位。 - clientWidth:返回自身包括
padding
和内容区的宽度
,不含边框(不包括滚动条)
,返回数值不带单位。 - scrollWidth:返回自身实际
内容宽度
+padding
,不含边框(不包括滚动条)
,返回数值不带单位。 - 若内容无溢出,scrollWidth === clientWidth
- 若内容溢出, scrollWidth > clientWidth (clientWidth = 视口宽度- margin-滚动条宽度)