# dom
DOM
或文档对象模型是 web 页面上所有对象的根。它表示文档的结构,并将页面连接到编程语言。它的结构是一个逻辑树。每个分支结束于一个节点,每个节点包含子节点、对象。
整个文档是一个文档节点,就想是树的根一样。
每个HTML元素都是元素节点。
HTML元素内的文本就是文本节点。
每个HTML属性时属性节点。
# 系统介绍document对象
属性 / 方法 | 描述 |
|---|---|
| document.activeElement | 返回当前获取焦点元素 |
| document.addEventListener() | 向文档添加句柄 |
| document.adoptNode(node) | 从另外一个文档返回 adapded 节点到当前文档。 |
| document.anchors | 返回对文档中所有 Anchor 对象的引用。 |
| document.applets | 返回对文档中所有 Applet 对象的引用。注意: HTML5 已不支持 <applet> 元素。 |
| document.baseURI | 返回文档的绝对基础 URI |
| document.body | 返回文档的body元素 |
| document.close() | 关闭用 document.open() 方法打开的输出流,并显示选定的数据。 |
| document.cookie | 设置或返回与当前文档有关的所有 cookie。 |
| document.createAttribute() | 创建一个属性节点 |
| document.createComment() | createComment() 方法可创建注释节点。 |
| document.createDocumentFragment() | 创建空的 DocumentFragment 对象,并返回此对象。 |
| document.createElement() | 创建元素节点。 |
| document.createTextNode() | 创建文本节点。 |
| document.doctype | 返回与文档相关的文档类型声明 (DTD)。 |
| document.documentElement | 返回文档的根节点 |
| document.documentMode | 返回用于通过浏览器渲染文档的模式 |
| document.documentURI | 设置或返回文档的位置 |
| document.domain | 返回当前文档的域名。 |
| document.domConfig | 已废弃。返回 normalizeDocument() 被调用时所使用的配置。 |
| document.embeds | 返回文档中所有嵌入的内容(embed)集合 |
| document.forms | 返回对文档中所有 Form 对象引用。 |
| document.getElementsByClassName() | 返回文档中所有指定类名的元素集合,作为 NodeList 对象。 |
| document.getElementById() | 返回对拥有指定 id 的第一个对象的引用。 |
| document.getElementsByName() | 返回带有指定名称的对象集合。 |
| document.getElementsByTagName() | 返回带有指定标签名的对象集合。 |
| document.images | 返回对文档中所有 Image 对象引用。 |
| document.implementation | 返回处理该文档的 DOMImplementation 对象。 |
| document.importNode() | 把一个节点从另一个文档复制到该文档以便应用。 |
| document.inputEncoding | 返回用于文档的编码方式(在解析时)。 |
| document.lastModified | 返回文档被最后修改的日期和时间。 |
| document.links | 返回对文档中所有 Area 和 Link 对象引用。 |
| document.normalize() | 删除空文本节点,并连接相邻节点 |
| document.normalizeDocument() | 删除空文本节点,并连接相邻节点的 |
| document.open() | 打开一个流,以收集来自任何 document.write() 或 document.writeln() 方法的输出。 |
| document.querySelector() | 返回文档中匹配指定的CSS选择器的第一元素 |
| document.querySelectorAll() | document.querySelectorAll() 是 HTML5中引入的新方法,返回文档中匹配的CSS选择器的所有元素节点列表 |
| document.readyState | 返回文档状态 (载入中……) |
| document.referrer | 返回载入当前文档的文档的 URL。 |
| document.removeEventListener() | 移除文档中的事件句柄(由 addEventListener() 方法添加) |
| document.renameNode() | 重命名元素或者属性节点。 |
| document.scripts | 返回页面中所有脚本的集合。 |
| document.strictErrorChecking | 设置或返回是否强制进行错误检查。 |
| document.title | 返回当前文档的标题。 |
| document.URL | 返回文档完整的URL |
| document.write() | 向文档写 HTML 表达式 或 JavaScript 代码。 |
| document.writeln() | 等同于 write() 方法,不同的是在每个表达式之后写一个换行符。 |
# querySelector
- querySelector() 方法返回文档中匹配指定 CSS 选择器的一个元素。
- 注意:
querySelector() 方法仅仅返回匹配指定选择器的第一个元素。如果你需要返回所有的元素,请使用 querySelectorAll() 方法替代。
- 注意:
- 返回值:
匹配指定 CSS 选择器的第一个元素。 如果没有找到,返回 null。如果指定了非法选择器则 抛出 SYNTAX_ERR 异常。
document.querySelector("p");//获取文档中第一个 <p> 元素
document.querySelector(".example");//获取文档中 class="example" 的第一个元素
document.querySelector("p.example");//获取文档中 class="example" 的第一个 <p> 元素
document.querySelector("a[target]");//获取文档中有 "target" 属性的第一个 <a> 元素
2
3
4
以下实例演示了多个选择器的使用方法。
假定你选择了两个选择器: <h2> 和 <h3> 元素。
以下代码将为文档的第一个 <h2> 元素添加背景颜色:
<h2>A h2 element</h2>
<h3>A h3 element</h3>
document.querySelector("h2, h3").style.backgroundColor = "red";
2
3
4
但是,如果文档中 <h3> 元素位于 <h2> 元素之前,<h3> 元素将会被设置指定的背景颜色。
<h3>A h3 element</h3>
<h2>A h2 element</h2>
document.querySelector("h2, h3").style.backgroundColor = "red";
2
3
4
# URL
- URL 属性可返回当前文档的 URL。
document.URL
# getElementsByTagName
- getElementsByTagName() 方法可返回带有指定标签名的对象的集合。(参数值 "
*" 返回文档的所有元素。) - 返回值:
NodeList 对象——指定标签名的元素集合
# getElementById
- getElementById() 方法可返回对拥有指定 ID 的第一个对象的引用。
- HTML DOM 定义了多种查找元素的方法,除了 getElementById() 之外,还有
getElementsByName()和getElementsByTagName()。 - 如果没有指定 ID 的元素返回 null
- 如果存在多个指定 ID 的元素则返回第一个。
- 如果需要
查找到那些没有 ID 的元素,你可以考虑通过CSS选择器使用 querySelector()。
# createTextNode
//createTextNode() 可创建文本节点。
document.createTextNode(text)
2
var h=document.createElement("H1")
var t=document.createTextNode("Hello World");
h.appendChild(t);
2
3
# document.createElement
//createElement() 方法通过指定名称创建一个元素
document.createElement(nodename)
2
nodename——String——必须。创建元素的名称。
var btn=document.createElement("BUTTON");
var t=document.createTextNode("CLICK ME");
btn.appendChild(t);
2
3
# 什么是DOM及DOM操作
<!DOCTYPE html>
<html lang="en">
<head>
<title>A super simple title!</title>
</head>
<body>
<h1>A super simple web page!</h1>
</body>
</html>
2
3
4
5
6
7
8
9
在这个结构的顶部有一个document,也称为根元素,它包含另一个元素:html。 html元素包含一个head,而 head 又有一个title。 然后body 包含一个h1。 每个HTML元素都由特定类型(也称为接口)表示,并且可能包含文本或其他嵌套元素:
document (HTMLDocument)
|
| --> html (HTMLHtmlElement)
|
| --> head (HtmlHeadElement)
| |
| | --> title (HtmlTitleElement)
| | --> text: "A super simple title!"
|
| --> body (HtmlBodyElement)
| |
| | --> h1 (HTMLHeadingElement)
| | --> text: "A super simple web page!"
2
3
4
5
6
7
8
9
10
11
12
13
每个HTML元素都来自Element,但其中很大一部分都是专用的。 咱们可以检查原型以查找元素所属的“种类”。 例如,h1元素是HTMLHeadingElement:
document.querySelector('h1').__proto__
// Output: HTMLHeadingElement
2
3
而HTMLHeadingElement则是HTMLElement的后代:
document.querySelector('h1').__proto__.__proto__
// Output: HTMLElement
2
3
# document 和 window 之间的区别
简单来说,document是window的一个对象属性。window 对象表示浏览器中打开的窗口。如果文档包含框架(frame 或 iframe 标签),浏览器会为 HTML 文档创建一个 window 对象,并为每个框架创建一个额外的 window 对象。所有的全局函数和对象都属于 window 对象的属性和方法。
window 指窗体。document指页面。document是window的一个子对象。- 用户不能改变 document.location(因为这是当前显示文档的位置)。但是,可以改变window.location (用其它文档取代当前文档)window.location本身也是一个对象,而document.location不是对象。
document接口有许多实用方法,比如
querySelector(),它是用于查找给定页面内HTML元素的方法:
document.querySelector('h1');
window表示当前的浏览器,下面代码与上面等价:
window.document.querySelector('h1');
window是一个全局对象,可以从浏览器中运行的任何JS代码直接访问。 window暴露了很多属性和方法,如:
window.alert('Hello world'); // Shows an alert
window.setTimeout(callback, 3000); // Delay execution
window.fetch(someUrl); // make XHR requests
window.open(); // Opens a new tab
window.location; // Browser location
window.history; // Browser history
window.navigator; // The actual user agent
window.document; // The current page
2
3
4
5
6
7
8
因为这些属性和方法也是全局的,所以也可以这样访问它们
alert('Hello world'); // Shows an alert
setTimeout(callback, 3000); // Delay execution
fetch(someUrl); // make XHR requests
open(); // Opens a new tab
location; // Browser location
history; // Browser history
navigator; // The actual user agent
document;// The current page
2
3
4
5
6
7
8
其中有些咱们都已经很熟悉了,如setTimeout() 的方法。 例如,当咱们想要得知当前用户的浏览器语言时,
window.navigator就非常有用:
if (window.navigator) {
var lang = window.navigator.language;
if (lang === "en-US") {
// show something
}
if (lang === "it-IT") {
// show something else
}
}
2
3
4
5
6
7
8
9
10
# DOM常用方法
# 获取节点
// 通过id号来获取元素,返回一个元素对象
document.getElementById(idName);
// 通过name属性获取id号,返回元素对象数组
document.getElementsByName(name)
// 通过class来获取元素,返回元素对象数组
document.getElementsByClassName(className);
// 通过标签名获取元素,返回元素对象数组
document.getElementsByTagName(tagName);
2
3
4
5
6
7
8
# 获取/设置元素的属性值
// 括号传入属性名,返回对应属性的属性值
element.getAttribute(attributeName);
// 传入属性名及设置的值
element.setAttribute(attributeName,attributeValue);
2
3
4
# 创建节点Node
// 创建一个html元素,这里以创建h3元素为例
document.createElement("h3");
// 创建一个文本节点;
document.createTextNode(String);
// 创建一个属性节点,这里以创建class属性为例
document.createAttribute("class");
2
3
4
5
6
# 增添节点
// 往element内部最后面添加一个节点,参数是节点类型
element.appendChild(Node);
// 在element内部的中在existingNode前面插入newNode
elelment.insertBefore(newNode,existingNode);
2
3
4
# DOM常用属性
- 获取当前元素的父节点
// 返回当前元素的父节点对象
element.parentNode;
2
- 获取当前元素的子节点
// 返回当前元素所有子元素节点对象,只返回HTML节点
element.chlidren;
// 返回当前元素多有子节点,包括文本,HTML,属性节点。(回车也会当做一个节点)
element.chilidNodes;
// 返回当前元素的第一个子节点对象
element.firstChild;
// 返回当前元素的最后一个子节点对象
element.lastChild;
2
3
4
5
6
7
8
- 获取当前元素的同级元素
// 返回当前元素的下一个同级元素 没有就返回null
element.nextSibling;
// 返回当前元素上一个同级元素 没有就返回 null
element.previousSibling;
2
3
4
- 获取当前元素的文本
// 返回元素的所有文本,包括html代码
element.innerHTML;
// 返回当前元素的自身及子代所有文本值,只是文本内容,不包括html代码
element.innerText;
2
3
4
- 获取当前节点的节点类型
// 返回节点的类型,数字形式(1-12)
// 常见几个1:元素节点,2:属性节点,3:文本节点。
node.nodeType
2
3
- 设置样式
// 设置元素的样式时使用style
element.style.color=“#eea”;
2
# DOM操作
- DOM中的每个HTML元素也是一个节点,可以像这样查找节点:
document.querySelector('h1').nodeType;
//上面会返回1,它是Element类型的节点的标识符,还可以检查节点名称:
document.querySelector('h1').nodeName;
//"H1"
2
3
4
咱们主要使用DOM中的两种类型的节点:
元素节点
文本节点
//创建元素节点,可以通过 createElement方法:
var heading = document.createElement('h1');
//创建文本节点,可能通过 createTextNode 方法:
var text = document.createTextNode('Hello world');
//接着将两个节点组合在一起,然后添加到 body 上:
heading.appendChild(text);
document.body.appendChild(heading)
2
3
4
5
6
7
# 13个需要知道的方法:使用 JavaScript 来操作 DOM
# document.querySelector / document.querySelectorAll
document.querySelector方法返回文档中与指定选择器或选择器组匹配的第一个 html 元素。如果找不到匹配项,则返回null。document.querySelectorAll方法返回与指定的选择器组匹配的文档中的元素列表 (使用深度优先的先序遍历文档的节点)。返回的对象是 NodeList 。
// 返回第一个 ul 元素
const list = document.querySelector('ul')
// 返回所有类名为 info 或者 warning 的 div 元素
const elements = document.querySelectorAll('div.info, div.warning');
2
3
4
# document.createElement2
在一个 HTML 文档中, document.createElement(tagName) 方法创建由 tagName 指定的 HTML 元素,或一个HTMLUnknownElement,如果tagName不被识别。
# Node.appendChild
Node.appendChild()方法将节点添加到给定父节点的子节点列表的末尾。请注意,如果给定的子代是文档中现有节点的引用,则它将移动到新位置。看看示例:
let list = document.createElement('ul');
['北京', '上海', '深圳'].forEach(city => {
let listItem = document.createElement('li')
listItem.innerText = city
list.appendChild(listItem)
})
document.body.appendChild(list)
2
3
4
5
6
7
# Node.insertBefore
此方法在给定的父节点内的子引用节点之前插入给定节点(并返回插入的节点)
let list = document.querySelector('ul');
let firstCity = list.querySelector('ul > li');
let newCity = document.createElement('li');
newCity.textContent = 'San Francisco';
list.insertBefore(newCity, firstCity);
2
3
4
5
# Node.removeChild
Node.removeChild方法从DOM中删除一个子节点并返回删除的节点。请注意,返回的节点不再是DOM的一部分,而是仍存在于内存中。如果处理不当,可能会导致内存泄漏。
let list = document.querySelector('ul');
let firstItem = list.querySelector('li');
let removedItem = list.removeChild(firstItem);
2
3
# Node.replaceChild
此方法替换父节点中的子节点(并返回替换后的旧子节点)。请注意,如果处理不当,此方法可能导致与Node.removeChild类似的内存泄漏问题。
let list = document.querySelector('ul');
let oldItem = list.querySelector('li');
let newItem = document.createElement('li');
newItem.innerHTML = '前端小智';
let replacedItem = list.replaceChild(newItem, oldItem);
2
3
4
5
# Node.cloneNode
Node.cloneNode(deep) 方法返回调用该方法的节点的一个副本,**deep(可选)**表示是否采用深度克隆,如果为true,则该节点的所有后代节点也都会被克隆,如果为false,则只克隆该节点本身.
let list = document.querySelector('ul');
let clone = list.cloneNode();
2
# Element.getAttribute / Element.setAttribute
Element.getAttribute方法返回元素上给定属性的值,反之亦然,Element.setAttribute设置给定元素上属性的值。
let list = document.querySelector('ul');
list.setAttribute('id', 'my-list');
let id = list.getAttribute('id');
console.log(id); // outputs my-list
2
3
4
# Element.hasAttribute / Element.removeAttribute
Element.hasAttribute方法检查给定元素是否具有指定的属性,返回值为boolean。通过调用Element.removeAttribute方法,我们可以从元素中删除具有给定名称的属性。
let list = document.querySelector('ul');
if (list.hasAttribute('id')) {
console.log('list has an id');
list.removeAttribute('id');
};
2
3
4
5
# Element.insertAdjacentHTML
element.insertAdjacentHTML(position, text) 将指定的文本解析为HTML或XML,并将结果节点插入到DOM树中的指定位置。它不会重新解析它正在使用的元素,因此它不会破坏元素内的现有元素。这避免了额外的序列化步骤,使其比直接innerHTML操作更快。
- position是相对于元素的位置,并且必须是以下字符串之一:
- beforebegin:元素自身的前面。
- afterbegin:插入元素内部的第一个子节点之前。
- beforeend:插入元素内部的最后一个子节点之后。
- afterend:元素自身的后面。
- text是要被解析为HTML或XML,并插入到DOM树中的字符串。
<!-- beforebegin -->
<div>
<!-- afterbegin -->
<p>Hello World</p>
<!-- beforeend -->
</div>
<!-- afterend -->
2
3
4
5
6
7
var list = document.querySelector('ul');
list.insertAdjacentHTML('afterbegin', '<li id="first-item">First</li>');
2
# Dom 节点和 元素 有啥区别
DOM文档由节点层次结构组成。每个节点可以具有
父级和/或子级。
<!DOCTYPE html>
<html>
<head>
<title>My Page</title>
</head>
<body>
<!-- Page Body -->
<h2>My Page</h2>
<p id="content">Thank you for visiting my web page!</p>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
<html>是文档树中的一个节点。它有2个子节点:<head>和<body>。<body>子有3个子节点的节点:注释节点 <!-- Page Body -->,标题<h2>,段落<p>。<body>节点的父节点是<html>节点。- HTML文档中的标记代表一个节点,有趣的是普通文本也是一个节点。段落节点
<p>有1个子节点:文本节点“Thank you for visiting my web page!”。
# 节点类型
在于DOM Node接口,尤其是
Node.nodeType属性。
- Node.ELEMENT_NODE
- Node.ATTRIBUTE_NODE
- Node.TEXT_NODE
- Node.CDATA_SECTION_NODE
- Node.PROCESSING_INSTRUCTION_NODE
- Node.COMMENT_NODE
- Node.DOCUMENT_NODE
- Node.DOCUMENT_TYPE_NODE
- Node.DOCUMENT_FRAGMENT_NODE
- Node.NOTATION_NODE
const paragraph = document.querySelector('p');
paragraph.nodeType === Node.ELEMENT_NODE; // => true
2
3
代表整个节点文档树的节点类型为Node.DOCUMENT_NODE:
document.nodeType === Node.DOCUMENT_NODE; // => true
元素是节点的子类型,就像猫是动物的子类型一样
节点类型的以下属性评估为一个节点或节点集合(NodeList):
node.parentNode; // Node or null
node.firstChild; // Node or null
node.lastChild; // Node or null
node.childNodes; // NodeList
2
3
4
5
6
但是,以下属性是元素或元素集合(HTMLCollection):
node.parentElement; // HTMLElement or null
node.children; // HTMLCollection
2
3
由于
node.childNodes和node.children都返回子级列表,因此为什么要同时具有这两个属性?
const paragraph = document.querySelector('p');
paragraph.childNodes; // NodeList: [HTMLElement, Text]
paragraph.children; // HTMLCollection: [HTMLElement]
2
3
4
paragraph.childNodes集合包含2个节点:<b>Thank you</b>,,以及for visiting my web page!文本节点!
但是,paragraph.children集合仅包含1个项目:<b>Thank you</b>。
由于paragraph.children仅包含元素,因此此处未包含文本节点,因为其类型是文本(Node.TEXT_NODE),而不是元素(Node.ELEMENT_NODE)。
同时拥有node.childNodes和node.children,我们可以选择要访问的子级集合:所有子级节点或仅子级是元素。