01、DOM(document
)
DOM(Document Object Model)文档对象模型,将文档document解析为一个由节点和对象(包含属性和方法的对象)组成的逻辑树,每个节点都是一个对象,**document**
对象就是整个DOM树的根节点。DOM提供的API方法用来管理这棵树,用JavaScript 等脚本语言操作文档结构、样式和内容。
1.1、DOM结构-节点/元素
DOM树是有很多节点构成,分为下面几种类型,注意节点是包含文本、注释的。
节点类型 | 描述 | 示例 |
---|---|---|
**document** 文档节点 |
文档本身document,DOM的入口(根) | document |
**element** 元素节点 |
所有HTML元素Element /ˈelɪmənt/ i |
html、body、a、p |
**attribute** 属性节点 |
元素的属性 | id、name、href、class |
文本节点 | 元素内的文本形成文本节点 | 包括换行、空格 |
注释节点 | 注释 |
一颗完整的DOM树,除了显而易见的元素、节点,还有注释、换行符构成的文本类节点。
<!DOCTYPE HTML>
<html>
<body>
The truth about elk.
<ol>
<li>An elk is a smart</li>
<!-- comment -->
<li>...and cunning animal!</li>
</ol>
</body>
</html>
:::danger
当前选择元素$0:在浏览器控制台中,$0
标识当前选中的元素。$0.style.background='red';
:::
节点和元素在DOM树上的不同视图(导航方式)如下图,现代JS中主要使用元素导航属性。
节点-导航属性 | 描述 | 元素-导航属性 | 描述 |
---|---|---|---|
parentNode |
父节点 | **parentElement** |
父元素,一般和parentNode一样 ,只有document.documentElement不同 |
firstChild |
第一个子节点 | **firstElementChild** |
第一个子元素 |
lastChild |
最后一个子节点 | **lastElementChild** |
最后一个子元素 |
childNodes |
子节点集合 | **children** |
子元素集合 |
nextSibling |
下一个兄弟节点 | **nextElementSibling** |
下一个兄弟元素( Sibling/ˈsɪblɪŋ/ 兄弟) |
previousSibling |
上一个兄弟节点 | **previousElementSibling** |
上一个兄弟元素 |
document.documentElement.parentNode; //HTMLDocument
document.documentElement.parentElement; //null
document.body.childNodes.length; //33
document.body.children.length; //16
document.body.firstElementChild;
:::warning ❓元素节点:都是只读的,不可用于插入、修改元素;都是实时的;集合是可迭代的,用for..of,不要用for(in) :::
1.2、节点Node/元素Element
节点/元素的继承层次结构如下,最基础的EventTarget 又继承自Object,因此可以自由添加属性、方法。
- EventTarget :—— 是一切的根“抽象(abstract)”类,定义了基础的事件。
- Node :也是一个“抽象”类,充当 DOM 节点的基础,提供了节点导航功能,如parentNode,nextSibling,childNodes 等。
- Document :表示整个文档,全局变量
document
就是他。 - CharacterData:一个文本“抽象”类,被Text(文本节点) 、Comment (注释节点)继承。
- Element :是 DOM 元素的基础类,提供了元素导航功能,如nextElementSibling,children等,以及搜索方法etElementsByTagName 和 querySelector等。
- HTMLElement :所有 HTML 元素的基础类,常用的如:HTMLInputElement、HTMLBodyElement、HTMLAnchorElement、HTMLDivElement、HTMLTableElement
document.body.querySelector("div").constructor.name; //HTMLDivElement document.body.querySelector("div").toString(); //[object HTMLDivElement]
Node节点
Node节点对象的属性:
Node 属性/方法 | 描述 |
---|---|
data | 文本/注释节点的文本值,可修改,注释节点可用来存放一些待处理内容 |
nodeName | 节点名称 |
textContent | 元素内文本,去掉所有 |
appendChild(node) | 从末尾追加一个子节点,支持字符串参数 |
removeChild(child) | 删除一个子节点 |
replaceChild(new,old) | 替换一个子节点 |
insertBefore(new,ref) | 在ref节点前插入一个节点 |
cloneNode(deep) | 克隆当前节点副本,deep=true会克隆其所有后代,否则只是节点本身 |
contains( node) | 是否包含指定的后代节点,返回bool |
hasChildNodes() | 是否包含子节点,返回bool |
Element 元素
Element 基类元素对象提供的属性方法:
Element 属性 | 描述 |
---|---|
id | 唯一id,基础通用属性还要name、class、style |
localName | 本地化名称,名称相关的还有nodeName、tagName |
attributes | 所有属性节点的一个实时集合,支持移除项、属性值操作 |
classList、className | class样式集合、class样式值,集合可以新增、删除。 |
innerHTML | 元素标签内的所有HTML内容,可以修改,注意innerHTML+= 会进行完全重写 |
outerHTML | 包含元素本身及其内部的所有HTML内容,可以修改(删除并替换) |
innerText | 元素标签内的所有文本节点值,包含所有后代节点的文本。 |
hidden | 是否隐藏的bool属性, |
方法 | |
addEventListener() | 注册事假到EventTarget,还有配套的removeEventListener() |
append(node…) | 在末尾追加多个子节点(或DOMString=text节点) |
prepend(node…) | 在开头插入多个子节点(或DOMString) |
after(node…) | 在后面插入节点(或DOMString) |
before(node…) | 在前面插入节点(或DOMString) |
replaceWith(node) | 将 node 替换为给定的节点或字符串 |
remove(element) | 把对象从它所属的 DOM 树中删除 |
scroll()/scrollBy() | 元素内滚动 |
事件(event) | |
blur(event)、focusout() | 元素失去焦点,blur不会冒泡 (blue /blɜːr/ 模糊) |
focus、focusin | 元素获取焦点时触发,focus不会冒泡 |
keydown、keyup | 键盘按键按下、松开时触发 |
click(event) | 点击触发,通常是鼠标左键在一个元素上被按下并放开时 |
dblclick | 双击触发事件 |
mousedown、mouseup | 鼠标按下、弹起时触发 |
mousemove | 鼠标在元素上移动时触发 |
onmouseover、mouseout | 鼠标移入、移出元素区域时触发 |
mouseenter、mouseleave | 鼠标移入、移出元素区域时触发,与上面不同的不会冒泡 |
<div class="h1 c2" id="firstDiv" myatt="自定义特性" order="asc"></div>
<script>
document.body.querySelector("div").attributes["class"]="c2 c3 c4"; //设置属性值
document.body.querySelector("div").classList.add("c5");
document.body.querySelector("div").setAttribute("att2",3) //添加、设置属性值
document.body.querySelector("#firstDiv").addEventListener("click",
(event) => {
console.log(event)
});
</script>
:::warning
注意:DOM操作必须等节点初始化完成后才能进行。可以在html尾部执行JS,或者在window
的onload
事假中处理
:::
1.3、元素特性Attribute
元素特性的操作方法:
Element-特性方法 | |
---|---|
attributes | 所有属性节点的一个实时集合,支持移除项、属性值操作,ele.attributes["href"].value |
getAttribute(attName) | 获取属性值 |
getAttributeNames() | 所有属性名数组 |
setAttribute(attName,value) | 设置属性值,可以新增自定义特性,常用于设置css |
removeAttribute(attName) | 从指定的元素中删除一个属性 |
hasAttribute(attName) | 判断是否包含指定属性,返回一个布尔值 |
hasAttributes(attname) | 判断是否包含属性,返回一个布尔值 |
- 特性(attribute)—— 写在 HTML 中的内容,值都是字符串,大小写不明感。
属性(property)—— DOM 对象中的内容,大小写敏感。 :::warning ❗特性attribute与属性property:元素上的特性attribute与属性property基本上都是一致相对应的。也有个别例外,如
input.value
只能单向从特性attribute同步到属性property。 :::<style> span[data-status="success"] { color: green; } span[data-status="failure"] { color: red; } </style> <div> <span data-status="success">操作结果</span> <!--自定义特性用来设置元素状态样式--> </div> <script> const espan = document.querySelector("span[data-status]"); console.log(espan.attributes); //所有属性集合 console.log(espan.hasAttribute("data-status")); //切换样式 espan.attributes["data-status"].value="failure"; espan.dataset.status="failure"; espan.setAttribute("data-status","failure"); espan.class="success"; </script>
dataset 属性用来存放自定义的非标准特性,需要自定义的特性都以“data-”开头,这是专门保留给程序猿门使用的。
以“data-”开头命名非标准特性,如“data-status”,通过
elem.dataset.status
访问。- 这样可以避免HML语言升级后造成的名称冲突。
1.4、元素的大小位置
| Element-大小位置 | 描述 | | —- | —- | | clientHeight、clientWidth | 元素内部高度、宽度,包括内边距(不含边框) | | offsetWidth/offsetHeight | 元素完整的宽度、高度,为元素的完整大小,包括border | | clientTop/Left | 元素边框宽度,同border宽度 | | offsetLeft/Top | 元素相对于 offsetParent 左上角的 x/y 坐标 | | scrollHeight 、Width | 元素滚动视图的高度、宽度,包含滑动隐藏部分。 | | scrollLeft/scrollTop | 元素滚出去(隐藏)的部分宽度、高 |
1.5、document
document 属性 | 描述 |
---|---|
documentElement | 对应 标签的 顶层节点 |
all、head、body | 所有元素的集合、head节点、body节点 |
images | 所有图片元素集合 |
forms | 所有表单元素 |
links | 所有超链接的列表 |
scripts | 所有的 |