DOM简介
- DOM(文档对象模型) 是一项 W3C标准。
- DOM 模型被结构化为对象树。
- DOM 本质:从html文件提取出个一棵树。
- DOM 是关于如何获取、更改、添加或删除 HTML 元素的标准。
Document 对象
文档对象代表您的网页。访问 HTML 页面中的任何元素,总是从访问 document 对象开始。
DOM 节点
节点类型
根据 W3C HTML DOM 标准,HTML 文档中的所有事物都是节点:
- 整个文档是文档节点
- 每个 HTML 元素是元素节点
- HTML 元素内的文本是文本节点
- 每个 HTML 属性是属性节点
- 所有注释是注释节点
DOM 处理中的一种常见错误是认为元素节点中包含文本。而应该是元素节点包含了文本节点。
DOM 根节点
有两个特殊属性允许访问完整文档:document.body
:文档的 body
document.documentElement
:文档的html
(完整文档)
获取文本节点的值
- 可以通过节点的
innerHTML
属性进行访问。 - 也可以访问首个子节点的
nodeValue
。
<title id="demo">DOM 教程</title>
<script>
//方法一
let myTitle = document.getElementById("demo").innerHTML;
//方法二
let myTitle = document.getElementById("demo").firstChild.nodeValue;
//方法三
let myTitle = document.getElementById("demo").childNodes[0].nodeValue;
</script>
attribute 和 property
DOM有其默认的基本属性,而这些属性就是所谓的property,无论如何,它们都会在初始化的时候再DOM对象上创建。如果在html标签中对这些属性进行赋值,那么这些值就会作为初始值赋给DOM的同名property。
property:是DOM对象上的属性,
attribute:是html标签上的特性:包含自定义属性。有三个方法setAttribute
、getAttribute
、removeAttribute
;
- 对于DOM元素节点默认的基本属性,无论哪一方面发生改变,都会互相影响。
- 对于自定义的属性,任何一方改变都不会影响到另一方。且对于arrtibute设置的自定义属性,会体现到html 结构中,而property 自定义的属性,不会体现到html 结构中。
<div id="div1" class="divClass" title="divTitle" title1="divTitle1">测试</div>
<script>
let in1 = document.getElementById("div1");
in1.abcdefg = "abcdefg"; //设置自定义property属性
in1.setAttribute("att", "aaa"); //设置自定义attribute 属性
in1.title = "theTitle"; //修改DOM默认属性
in1.setAttribute("class", "theClass");//修改DOM默认属性
</script>
节点关系
父(parent)、子(child)和同胞(sibling)用于描述这些关系。
在节点之间导航
通过 JavaScript,您可以使用以下节点属性在节点之间导航:
- parentNode
- childNodes[nodenumber]
- firstChild
- lastChild
- nextSibling
- previousSibling
children和childNodes的区别children
:只包含元素节点childNodes
:包含所有类型的节点
节点属性
nodeName 属性
规定节点的名称。只读。总是包含 HTML 元素的大写标签名。
- 元素节点的 nodeName 等同于标签名
- 属性节点的 nodeName 是属性名称
- 文本节点的 nodeName 总是 #text
- 文档节点的 nodeName 总是 #document
nodeValue 属性
规定节点的值。可写。
- 元素节点的 nodeValue 是 undefined
- 文本节点的 nodeValue 是文本文本
- 属性节点的 nodeValue 是属性值
nodeType 属性
返回节点的类型。只读。
DOM 节点操作
查找 HTML 元素
通过 id 查找 HTML 元素
//查找 id="intro" 的元素:
let myElement = document.getElementById("intro");
通过标签名查找 HTML 元素
//查找 id="main" 的元素,然后查找 "main" 中所有 <p> 元素:
let x = document.getElementById("main");
let y = x.getElementsTagName("p");
通过类名查找 HTML 元素
//返回包含 class="intro" 的所有元素的列表:
let x = document.getElementsByClassName("intro");
通过 CSS 选择器查找 HTML 元素
需要查找匹配指定 CSS 选择器(id、类名、类型、属性、属性值等等)的所有 HTML 元素,请使用 querySelectorAll() 方法。
//返回 class="intro" 的所有 <p> 元素列表:
let x = document.querySelectorAll("p.intro");
通过 HTML 对象集合查找 HTML 元素
//查找 id="frm1" 的 form 元素,在 forms 集合中,然后显示所有元素值:
let x = document.forms["frm1"];
let text = "";
for(let i = 0; i<x.length;i++){
text += x.elements[i],value+"<br>";
}
document.getElementById("demo").innerHTML = text;
属性 | 描述 | DOM |
---|---|---|
document.anchros | 返回拥有 name 属性的所有 元素。 | 1 |
document.body | 返回<body>元素 | 1 |
document.cookie | 返回文档的 cookie | 1 |
document.forms | 返回所有 <form> 元素 | 1 |
document.images | 返回所有 <img> 元素 | 1 |
document.title | 返回 <title> 元素 | 1 |
document.documentElement | 返回 <html> 元素 | 3 |
document.head | 返回 <head> 元素 | 3 |
document.scripts | 返回所有 <script> 元素 | 3 |
改变 HTML
改变 HTML 输出流document.write()
可用于直接写入 HTML 输出流:千万不要在文档加载后使用 document.write()
。这么做会覆盖文档。
改变 HTML 内容
使用 innerHTML 属性。
document.getElementById(id).innerHTML = 'new text'
改变属性的值
document.getElementById("myImage").src = "landscape.jpg";
改变 CSS
语法:document.getElementById(id).style.property = new style
document.getElementById("p2").style.color = "blue";
DOM 结构操作
如需向 HTML DOM 添加新元素,您必须首先创建这个元素(元素节点),然后将其追加到已有元素。
添加新 HTML 元素(节点)
创建新 HTML 元素(节点)
document.createElement("p");
document.createTextNode("这是新文本。");
追加到已有元素
para.appendChild(node); //追加新元素作为父的最后一个子。
element.insertBefore(para, child);//将para插入到父元素element下的child子元素前面
示例:
<div id="div1">
<p id="p1">这是一个段落。</p>
<p id="p2">这是另一个段落。</p>
</div>
<script>
var para = document.createElement("p");
var node = document.createTextNode("这是新文本。");
para.appendChild(node);
var element = document.getElementById("div1");
element.appendChild(para);
</script>
删除已有 HTML 元素
如需删除某个 HTML 元素,您需要知晓该元素的父节点。
常见的方法:找到你想要删除的子节点,并利用其 parentNode 属性找到父节点。
示例:
<div id="div1">
<p id="p1">这是一个段落。</p>
<p id="p2">这是另一个段落。</p>
</div>
<script>
//方法一
let parent = document.getElementById("div1");
let child = document.getElementById("p1");
parent.removeChild(child);
//方法二
let child = document.getElementById("p1");
child.parentNode.removeChild(child);
</script>
替换 HTML 元素
如需替换元素的,请使用 replaceChild() 方法。
<div id="div1">
<p id="p1">这是一个段落。</p>
<p id="p2">这是另一个段落。</p>
</div>
<script>
let para = document.createElement("p");
let node = document.createTextNode("这是新文本。");
para.appendChild(node);
let parent = document.getElementById("div1");
let child = document.getElementById("p1");
parent.replaceChild(para, child);
</script>
DOM 集合与节点列表
DOM集合:HTMLCollection 对象
HTMLCollection 对象是类数组的 HTML 元素列表(集合)。但它并非是数组。无法对 HTMLCollection 使用数组方法,比如 valueOf()、pop()、push() 或 join()。
length 属性定义了 HTMLCollection 中元素的数量。getElementsByTagName()
方法返回 HTMLCollection
对象。
//下面的代码选取文档中的所有 <p> 元素:
var x = document.getElementsByTagName("p");
DOM 节点列表:NodeList 对象
NodeList 对象是从文档中提取的节点列表(集合)。NodeList 对象与 HTMLCollection 对象几乎相同。
所有浏览器都会为 childNodes
属性返回 NodeList
对象。
大多数浏览器会为 querySelectorAll()
方法返回 NodeList
对象。
HTMLCollection 与 NodeList 的区别
- HTMLCollection是 HTML 元素的集合。NodeList 是文档节点的集合(元素节点+包含属性节点和文本节点)。
- 访问 HTMLCollection 项目,可以通过它们的名称、id 或索引号。访问 NodeList 项目,只能通过它们的索引号。
DOM 性能
避免频繁的DOM操作:
采用事件代理避免了频繁的操作DOM
将频繁操作改为一次性操作
let pList = document.getElementsByClassName("para");
let frag = document.createDocumentFragment();
for (let i = 0; i < 5; i++) {
let span = document.createElement("span");
span.innerHTML = `${i}`;
frag.appendChild(span);
}
pList[0].appendChild(frag);
对DOM查询做缓存
// 不缓存DOM查询结果
for (let i = 0; i < document.getElementsByTagName('p').length; i++) {
//每次循环,都会计算 length ,频繁进行DOM 查询
}
const pList = document.getElementsByTagName('p');
const length = pList.length;
for (let i = 0; i < length; i++) {
//缓存length,只进行一次DOM查询
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。