前言
DOM介绍
1、DOM基本知识
2、DOM操作
3、DOM类型
DOM (文档对象模型)是对 HTML 和 XML 文档操作的编程接口。DOM 的功能就是针对页面上的文档元素进行增、删、改。DOM 发光与得利于 DHTML (动态 HTML )的出现。DOM 是跨平台的应用编程接口(API)。DOM 的地位非常重要,所以 W3C 1998年10月1日发布了DOM Level 1 规范。下面是 DOM 规范所提供的功能和 DOM 规范的时间表
时间表
规范 | 草案 | 时间 |
DOM Level 1 | 1998年10月1日 | |
DOM Level 1(SE) | 2000年9月29日 | |
DOM Level 2 Core | 2000年11月13日 | |
DOM Level 2 Views | 2000年11月13日 | |
DOM Level 2 Style | 2000年11月13日 | |
DOM Level 2 Events | 2000年11月13日 | |
DOM Level 2 Traversal-Range | 2000年11月13日 | |
DOM Level 2 HTML | 2003年1月9日 | |
DOM Level 3 Validation | 2004年1月27日 | |
DOM Level 3 Requirements | 2004年2月26日 | |
DOM Level 3 XPath | 2004年2月26日 | |
DOM Level 3 Views | 2004年2月26日 | |
DOM Level 3 Core | 2004年4月7日 | |
DOM Level 3 Load and Save | 2004年4月7日 | |
DOM Level 3 Events | 2007年12月21日 |
DOM 级别 1
DOM 级别1专注于 HTML 和 XML 文档模型。它含有文档导航和处理功能。
DOM 级别1于1998年10月1日成为 W3C 推荐标准。
第二版的工作草案在200年9月29日。
DOM 级别2
DOM 级别2对 DOM 级别1添加了样式表对象模型,并定义了操作附于文档之上的样式信息的功能性。
DOM 级别2同时还定义了一个事件模型,并提供了对 XML 命名空间的支持。
作为一项 W3C 推荐标准,DOM 级别2规范发布于200年11月13日。
DOM Level 2 核心
DOM Level 2 核心规定了访问和更改文档内容及结构的一个 API,此 API 同时包含用于 XML 的接口。
DOM Level 2 HTML
DOM Level 2 HTML 规定了操作HTML文档结构和内容的API。(这部分规范仍然是工作草案)
DOM Level 2 Views
DOM Level 2 规定了对文档视图进行访问和更改的 API。视图是与原文档相关联的表现形式或某种备用的表现形式。
DOM Level 2 Style
DOM Level 2 Style 规定了动态访问及更改内容样式表的 API。
DOM Level 2 Events
DOM Level 2 Events 规定了访问文档事件的 API。
DOM Level 2 Traversal-Range
DOM Level 2 Traversal-Range 规定了动态遍历和识别文档内容范围的 API。
DOM 级别3
DOM Level 3 规定了内容模型(DTD 和 Schemas)和文档验证。同时规定了文档加载和保存、文档查看、文档格式化和关键事件。
DOM Level 3 建立于 DOM Core Level 2之上。
DOM Level 3 Requirements
DOM Requirements 文档已经为 Level 3 requirements 进行了更新, 并于2000年4月12日发布为工作草案。
DOM Level 3 Core
DOM Level 3 Core 规定了访问和更改文档内容、结构及样式的一个 API。
DOM Level 3 Events
通过增加新的接口和新的事件集,DOM Level 3 Events API 对 Leven 2 Event API 的功能进行了扩展。
DOM Level 3 Load and Save
DOM Level 3 Content Model 规定了用于内容加载和保存、内容模型 (DTD and Schemas) 和文档验证支持的 API。
DOM Level 3 Views and Formatting
DOM Level 3 Views 规定了对文档视图进行访问和更改的 API。视图是与原文档相关联的表现形式或某种备用的表现形式
1.1 DOM结构介绍
DOM 可以将任何 HTML 和 XML 文档描述成一个由多层节点构成的结构。
就是说 DOM 构成关系是层级结构的(也可以说是树形结构),每个 DOM 元素都是一个节点。
看下下面的一段 HTML 的构成关系
<html> <head>标题</head> <body> <p>Hello, World!</p> </body> </html>
将上面的 HTML 转化为层级结构为:
文档节点是每个文档的根节点。在上面代码中文档节点节点只有一个根节点即<html>元素,我们称之为文档元素。每个文档只能有一个文档元素,在HTML中文档元素始终是<html>元素,在XML中任何元素都有可能成为文档元素。
1.2 NODE关系
文档中所有的节点和其他节点都存在着各自的关系。节点之间的关系可以理解成一颗树。它的根节点就是<html>元素,<header>又是<html>的子节点。而<body>也是<html>的子节点同时也是<header>的兄弟节点。
每个节点都有一个childNodes属性,该属性保存这这个节点下的所有子节点。childNodes是一个NodeList对象,NodeList对象是一种类似数组的对象,它是有序的集合,它可以用括号的方式来取得NodeList里面的值,它也存在length属性。NodeList里面的节点随着DOM结构的改变而改变,也就是说NodeList和DOM节点成映射关系,下面来看看例子。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html lang='zh-CN' xml:lang='zh-CN' xmlns='http://www.w3.org/1999/xhtml'> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> <title>DOM基础-节点关系</title> </head> <body> <ul id="dom"> <li>JAVASCRIPT</li> <li>JAVA</li> <li>PHP</li> <li>C#</li> </ul> <script> var dom = document.getElementById('dom'); console.log(dom.childNodes); //所有子节点 console.log(dom.childNodes[0]); //第一个子节点 console.log(dom.childNodes.item(1)); //同上面访问节点是一样的 console.log(dom.childNodes.length); //子节点个数 </script> </body> </html>
每个文档节点都有个一个parentNode属性,这个属性指向的是该节点的父节点,如果元素节点一直往上遍历会一直取到#docuemtn的parentNode为null为止
var dom = document.getElementById('dom'); do{ console.log(dom); }while(dom = dom.parentNode)
文档节点的 previousSibling 和 nextSibling 属性,分别指向的是当前节点的上一个兄弟节点和当前节点的下一个兄弟节点。在IE浏览器中(IE<9)当NodeList中只有一个节点时,previousSibling 和 nextSibling 都是null。
文档节点的 firstChild 和 lastChild 属性,分别指向第一个子节点和最后一个子节点。
下图是节点关系
示例代码:
var dom = document.getElementById('dom'); cleanTextNode(dom); //因为现代浏览器把空行也算一个文本节点,所以要清楚它们 var java = dom.childNodes[1]; //第二个节点<li>JAVA</li> console.log(java.previousSibling); //<li>JAVA</li>上一个兄弟节点 <li>JAVASCRIPT</li> console.log(java.nextSibling); //<li>JAVA</li>下一个兄弟节点<li>PHP</li> console.log(dom.firstChild); //第一个子节点<li>JAVASCRIPT</li> console.log(dom.lastChild); //最后一个子节点<li>C#</li> console.log(dom.childNodes[0]==dom.firstChild); //true childNodes[0]等于firstChild console.log(dom.childNodes[dom.childNodes.length-1]==dom.lastChild); //true lastChild等于最后一个子节点 function cleanTextNode(elem){ for(var i=0; i<elem.childNodes.length; i++){ var child = elem.childNodes[i]; if( (child.nodeType==3) && (/^\s+$/.test(child.nodeValue)) ){ elem.removeChild(child); } } return elem; }
DOM提供了一些操作节点的方法,常用的节点如下
appendChild(newNode) 向 childNodes 列表尾插入节点 参数:newNode 要插入的新节点
insertBefore(insertNode, firstNode) 向 firstNode 节点前面插入 insertNode 节点,如果 firstNode 为 null,则该方法和 appendChild 方法一样 参数:insertNode 要插入的节点、firstNode 参照节点
replaceChild(newNode, firstNode) 替换 childNodes 中的节点 参数:newNode 要替换的节点、firstNode 被替换的节点
removeChild(deleteNode) 删除 childNodes 中的节点 参数:deleteNode 要删除的节点
cloneNode(boolean) 克隆一个节点 参数:boolean 如果为 true 则深度克隆,反之只克隆当前节点
DOM操作
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html lang='zh-CN' xml:lang='zh-CN' xmlns='http://www.w3.org/1999/xhtml'> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>DOM基础</title> </head> <body> <div id="appendchild">appendChild -</div> <div id="insertbefore"><i>insertBefore</i> </div> <div id="replacechild">replaceChild</div> <div id="clonenode">cloneNode</div> <div id="removechild">removeChild</div> <button onclick="actAppendChild();"> appendChild </button> <button onclick="actInsertBefore();"> insertBefore </button> <button onclick="actReplaceChild();"> replaceChild </button> <button onclick="actCloneNode();"> cloneNode </button> <button onclick="actRemoveChild();"> removeChild </button> <script> var appendchild = _('appendchild'), insertbefore = _('insertbefore'), replacechild = _('replacechild'), clonenode = _('clonenode'), removechild = _('removechild'); var appendSon = document.createElement('b'), insertbeforeSon = document.createElement('b'), replacechildSon = document.createElement('p'); appendSon.innerHTML = 'appendChild节点'; insertbeforeSon.innerHTML = 'insertBefore节点'; replacechildSon.innerHTML = 'replaceChild后的节点'; function actAppendChild() { appendchild.appendChild(appendSon); } function actInsertBefore() { insertbefore.insertBefore(insertbeforeSon, insertbefore.childNodes[0]); } function actReplaceChild() { replacechild.parentNode.replaceChild(replacechildSon, replacechild); } function actCloneNode() { var n = clonenode.cloneNode(true); clonenode.appendChild(n); } function actRemoveChild() { removechild.parentNode.removeChild(removechild); } function _(elem) { return document.getElementById(elem); } </script> </body> </html>
DOM操作一些基本练习
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html lang='zh-CN' xml:lang='zh-CN' xmlns='http://www.w3.org/1999/xhtml'> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>javascript DOM练习</title> <style> body { background:#fff; } #p { border: 1px solid red; } #p p { border: 1px solid pink; } p { margin: 0; } #wrap { border: 1px solid #ff6600; padding: 10px; color: red; } #content { background: pink; } </style> </head> <body> <p id="append">每天我都会说:</p> <p id="prepend">打开电脑!</p> <b id="after">无法连接网络!</b> <br> <i id="before">我说我有事情需要处理!</i> <div id="content"> content </div> <script> //append 添加到一个元素的内部 appendTo一样道理 var append = _('append'); var appendSon = document.createElement('b'); appendSon.innerHTML = 'HI!'; append.appendChild(appendSon); //prepend 把元素添加到目标元素内部的第一个元素前面 var prepend = _('prepend'); var prependSon = document.createElement('b'); prependSon.innerHTML = '早上第一件事就是'; var s = prepend.insertBefore(prependSon, prepend.firstChild); //after 插入到指定元素后面 var after = _('after'); var afterSon = document.createElement('i'); afterSon.innerHTML = '找运维人员'; var nextNode = after.nextSibling; after.parentNode.insertBefore(afterSon, nextNode) //before 插入到指定元素前面 var before = _('before'); var beforeSon = document.createElement('b'); beforeSon.innerHTML = '同事说需要帮助,' before.parentNode.insertBefore(beforeSon, before); //wrap包裹元素 var content = _('content'); //被包裹元素 var div = $('<div id="wrap">包裹元素</div>'); //包裹的元素 content.parentNode.insertBefore(div, content); //向要包裹的上一个兄弟节点插入包裹标签 div.appendChild(content); //把待包裹节点插入到包裹节点里 function _(selector) { return document.getElementById(selector); } function $(elemStr) { var parseHtml = /^[^<]*(<.+>)[^>]*$/.exec(elemStr); var div = document.createElement('div'); div.innerHTML = parseHtml[1]; return div.children[0]; } function log(any) { console.log(any); } </script> </body> </html>
在DOM Level 1 Core 中,DOM 规定了12种 DOM 节点类型具体规定如下
ELEMENT_NODE = 1; //元素
ATTRIBUTE_NODE = 2; //属性
TEXT_NODE = 3; //文本
CDATA_SECTION_NODE = 4; //xml 注释节点
ENTITY_REFERENCE_NODE = 5;
ENTITY_NODE = 6;
PROCESSING_INSTRUCTION_NODE = 7;
COMMENT_NODE = 8; //注释
DOCUMENT_NODE = 9; //文档
DOCUMENT_TYPE_NODE = 10;
DOCUMENT_FRAGMENT_NODE = 11;
NOTATION_NODE = 12;
根据节点类型不同 nodeName, nodeValue 和 attributes 是不同的,下面我们来看一下其中的变化。
nodeType | nodeName | nodeValue | attributes |
Element | tagName(元素标签名) | null | NameNodeMap |
Attr | name of attribute(属性名) | value of attribute(属性值) | null |
Text | #text | content of the text node(文本内容) | null |
CDATASection | #cdata-section | content of the CDATA Section | null |
EntityReference | name of entity referenced | null | null |
Entity | entity name | null | null |
ProcessingInstruction | target | entire content excluding the target | null |
Comment | #comment | content of the comment | null |
Document | #document | null | null |
DocumentType | document type name | null | null |
DocumentFragment | #document-fragment | null | null |
Notation | notation name | null | null |
Document 类型
Document表示文档节点。在一个浏览器中 document 对象是 HTMLDocument的实例,document 也是 window 对象的一个属性,通过它我们可以快速的访问到文档中的子节点。
document对象实例的属性
1、documentElement 取得对<HTML>节点的引用
2、doctype 取得对<!DOCTYPE>节点的引用
3、body 取得对
DOM是web的核心,DOM涉及的东西也非常多。掌握好DOM是非常必要的。