DOM概述
DOM定义
DOM(文档对象模型,Document Object Model)是W3C组织开发的一套便于操作XML和HTML的JavaScript方法,其将XML和HTML抽象成文档对象(Document),并将其中所有的标签和内容都抽象成对象(节点),利用面向对象的思对XML和HTML的操作。其中 Document 对象是DOM的顶层节点。
XML(扩展标记语言,Extensible Markup Language),主要用于信息的存储和传送,HTML也是一种XML。
DOM组成
- DOM核心:针对任何结构化文档的标准模型。
- XML DOM:针对 XML 文档的标准模型。
- HTML DOM:针对 HTML 文档的标准模型。
XML DOM和HTML DOM的关系
XML DOM 是:用于 XML 的标准对象模型,用于 XML 的标准编程接口,中立于平台和语言的 W3C 标准。
XML DOM 定义了所有 XML 元素的对象和属性,以及访问它们的方法(接口)。
换言之:XML DOM 是用于获取、更改、添加或删除 XML 元素的标准。
HTML DOM 是:HTML 的标准对象模型,HTML 的标准编程接口的 W3C 标准。
HTML DOM 定义了所有 HTML 元素的对象和属性,以及访问它们的方法。
换言之,HTML DOM 是关于如何获取、修改、添加或删除 HTML 元素的标准。
其中,HTML DOM 是 XML DOM 的扩展,换言之,XML DOM 的方法均可以使用在HTML中,而反过来,HTML DOM 的方法不可以使用在XML中。
DOM树与节点
1. DOM树
对于HTML文档,DOM将所有的标签全部抽象成节点,并且节点间有严格的等级关系,以此形成一个DOM树。
如:
<!DOCTYPE html><html><head><meta charset = "utf-8" /><title> Demo </title></head><body><h1> DOM Lesson one </h1><p align="center" > Hello world! </p></body></html>
其对应的DOM树:
其中,每一行都是兄弟节点,绿色线条代表父子关系,而红色线条也是父子关系的一种,但是无法通过父亲查找孩子而找到。
2. 节点
2.1 节点分类
由DOM树可见,节点分为三种:元素节点(标签),属性节点和文本节点。
2.2 节点属性
nodeName,nodeValue,nodeType
具体如下:
节点类型/元素 | nodeName | nodeValue | nodeType |
元素节点 | 标签名 | 不可用 | 1 |
属性节点 | 属性名 | 属性的值 | 2 |
文本节点 | #text | 文本内容 | 3 |
document | #document | 不可用 | 9 |
2.3 节点关系
2.4 节点操作
操作目标节点的对象 | 添加 | 删除 | 修改 | 查询 |
当前节点 | document.createElement(name) node.setAttribute(name,value) | 不可用 | node.replaceNode(newNode) | document.getElementById(id) document.getElementsByName(name) document.getElementsByTagName(tagName) |
父节点 | node.appendChild(newNode) | node.removeChild(cNode) | node.replaceChild(newNode,oldNode) | 参见节点关系 |
绿色部分为HTML DOM方法。
DOM的使用
1. 基本属性与方法
属性
- nodeName:返回节点的名称,依据其类型。
- nodeType:返回节点的类型。
- attributes:返回元素的属性。
- childNodes:返回元素的子节点的 NodeList。
- firstChild:返回元素的首个子节点。
- lastChild:返回元素的最后一个子节点。
- parentNode:返回元素的父节点。
- nextSibling:返回元素之后紧跟的节点。
- previousSibling:返回元素之前紧随的节点。
- textContent:设置或返回元素及其后代的文本内容。
- innerTest:设置或返回元素后代的文本内容。
- innerHTML:设置或返回元素后代的内容。[HTML DOM]
方法
- hasAttribute(name):返回元素是否拥有指定的属性。
- hasAttributes():返回元素是否拥有属性。
- hasChildNodes():返回元素是否拥有子节点。
- createAttribute(node):创建属性节点。
- createElement(node):创建元素节点。
- createTextNode(node):创建文本节点。
- appendChild(node):向节点的子节点列表末尾添加新的子节点。
- cloneNode(include_all:true,false):克隆节点。
- removeAttribute(name):删除指定的属性。
- removeChild(node):删除子节点。
- replaceNode(newNode):替换节点。[仅IE]
- replaceChild(newNode, oldNode):替换子节点。
- getElementById(id):找到具有指定id的子孙元素。[HTML DOM]
- getElementsByName(name):找到具有指定name的子孙元素。[HTML DOM]
- getElementsByTagName(name):找到具有指定标签名的子孙元素。
- getAttribute(name):返回属性的值。
- setAttribute():添加新属性。
2. 获取标签内部的文本内容
XML DOM属性
- node.innerText;
- node.firstChild.nodeValue;
- node.lastChild.nodeValue;
- node.childNodes[0].nodeValue;
- node.textContent;[IE8]
HTML DOM属性
- node.innerHTML;
3. 读取子节点的内容
<!DOCTYPE html><html><head><meta charset = "utf-8" /><title> 读取指定的内容 </title><script type = "text/javascript" >function _getLi () {var bjNode = document . getElementById ( "bj" );var _childNodes = bjNode . childNodes ;for ( var i = 0 ; i < _childNodes . length ; i ++) {// 获取所有子节点,包括暗部(不显示在网页中的空格和制表符等)var n = _childNodes [ i ];// 如果子节点为元素,则获取改元素标签中的文本if ( n . nodeType == 1 ) {alert ( n . childNodes [ 0 ]. nodeValue );}}}</script></head><body><ul><li id = "bj" value = "beijing" >北京<h1> 海淀 </h1> 奥运</li><li id = "sh" value = "shanghai" >上海</li><br/><input type = "button" value = "li取值" onclick = " _getLi () " /></ul></body></html>
4. 获取孙子节点的文本内容
获取select下面option的文本内容。
HTML:
<!DOCTYPE html><html><head><meta charset = "utf-8" /><title> Demo </title><script type = "text/javascript" src = "js.js" ></script></head><body><select name = "edu" id = "edu" ><option value = "本科1" > 本科 </option><option value = "专科2" > 专科 </option><option value = "高中3" > 高中 </option><option value = "小学4" > 小学 </option><option value = "幼儿园5" > 幼儿园 </option></select></body></html>
4.1 使用XML DOM方法
方法1:获取select对象,获取childNodes,注意暗部。
var _selObj = document . getElementByTagName ( "select" )[ 0 ];var _childNodes = _selObj . childNodes ;for ( var i = 0 ; i < _childNodes . length ; i ++) {var n = _childNodes [ i ];// n可能获取到暗部,需要判断排除if ( n . nodeType == 1 ) {alert ( n . firstChild . nodeValue + " : " + n . getAttribute ( "value" ));}}
方法2:直接获取option对象集合
var optNodes = document . getElementsByTagName ( "option" );for ( var i = 0 ; i < optNodes . length ; i ++) {var n = optNodes [ i ];alert ( n . getAttribute ( "value" ));}
4.2 使用HTML DOM方法
获取select对象,并通过该对象的特有方法options直接获取option的对象集合,避免了暗部的影响。
var optNodes = document . getElementById ( "edu" ). options ;for ( var i = 0 ; i < optNodes . length ; i ++) {var n = optNodes [ i ];alert ( n . getAttribute ( "value" ));}
5. 节点的替换和复制
HTML:
<!DOCTYPE html><html><head><meta charset = "utf-8" /><title> 替换节点内容 </title><script type = "text/javascript" src = "js.js" ></script></head><body><ul><li id = "tar" onclick = " _changeNode () " > 点这里 </li><li> 湖南 </li><li> 山东 </li></ul><ul><li id = "game" > 打 <span style = " color : red " > 灰 </span> 机 </li><li> 抓泥鳅 </li><li> 斗地主 </li></ul></body></html>
5.1 使用当前节点或父节点替换
function _changeNode () {//1. 获取两个节点的对象var tarNode = document . getElementById ( "tar" );var gameNode = document . getElementById ( "game" );//2 替换节点//注意:当替换节点时,新节点将出现在被替换的位置,原位置将消失。// 通过当前节点替换tarNode . replaceNode ( gameNode ); // [仅IE]// 通过父节点替换//tarNode.parentNode.replaceChild(gameNode, tarNode);}
5.2 节点的克隆
function _changeNode () {//1. 获取两个节点的对象var tarNode = document . getElementById ( "tar" );//2. 克隆节点// cloneNode(true/false),true:包括子节点。false:不包括子节点(文本节点)。// 注意:当使用clone节点的时候,无论参数是true还是false都会把属性一起克隆,所以可能出现的是相同id的节点,所以不推荐使用克隆方法。var gameNode = document . getElementById ( "game" ). cloneNode ( true );tarNode . replaceNode ( gameNode ); // [仅IE]alert ( "gameNode clone id is " + gameNode . getAttribute ( "id" ));var oldgameNode = document . getElementsByTagName ( "li" )[ 3 ];alert ( "oldgaemNode id is " + oldgameNode . getAttribute ( "id" ));}
效果:
6. 节点的添加
HTML:
<!DOCTYPE html><html><head><meta charset = "utf-8" /><title> 添加节点 </title><script type = "text/javascript" src = "js.js" ></script></head><body><input type = "button" value = "添加选项" onclick = " _addOptions () " /><select><option> 博士 </option><option> 硕士 </option><option> 本科 </option></select></body></html>
6.1 使用XML DOM方法
function _addOptions () {var selObj = document . getElementsByTagName ( "select" )[ 0 ];var optNode = document . createElement ( "option" ); // 创建元素节点var txtNode = document . createTextNode ( "小学" ); // 创建文本节点optNode . appendChild ( txtNode ); // 给optNode添加子节点(文本节点)selObj . appendChild ( optNode ); // 给selObj添加子节点(option节点)}
6.2 使用HTML DOM的innerHTML方法[IE10+]
function _addOptions () {var selObj = document . getElementsByTagName ( "select" )[ 0 ];selObj . innerHTML += "<option>小学</option>" ;}
6.3 使用HTML DOM的对象方法
function _addOptions () {var selObj = document . getElementsByTagName ( "select" )[ 0 ];// option(text, value, defaultSelected, selected)// text:显示的文本// value:属性value的值// defaultSelected:初始化后选中的状态(true/false)// selected:当前选中的状态(true/false)var optNode = new Option ( "小学" , "小学" , true , true ); // 创建了一个Option对象selObj . add ( optNode );}
效果:
7. 表格动态增删
HTML:
<!DOCTYPE html><html><head><meta charset = "utf-8" /><title> 添加节点 </title><script type = "text/javascript" src = "js.js" ></script></head><body><table align = "center" cellpadding = "10" cellspacing = "3" ><tr><td> 姓名:<input type = "text" id = "username" /></td><td> Email:<input type = "text" id = "email" /></td><td> 年龄:<input type = "text" id = "age" /></td></tr><tr><td colspan = "3" align = "center" ><input type = "button" value = "添加" onclick = " _addTR () " /></td></tr></table><br/><br/><br/><hr/><table id = "tabInfo" align = "center" width = "500" border = "1" ><tr><td> 姓名 </td><td> Email </td><td> 年龄 </td><td> 操作 </td></tr></table></body></html>
7.1 使用XML DOM方法
function _addTR () {// 获取输入框信息var tablenode = document . getElementById ( "tabInfo" );var uname = document . getElementById ( "username" ). value ;var email = document . getElementById ( "email" ). value ;var age = document . getElementById ( "age" ). value ;// 创建一行var trNode = document . createElement ( "tr" );// 创建出一个单元格var unameTd = document . createElement ( "td" );var emailTd = document . createElement ( "td" );var ageTd = document . createElement ( "td" );var dropTd = document . createElement ( "td" );// 创建文本节点和删除节点var unameTxt = document . createTextNode ( uname );var emailTxt = document . createTextNode ( email );var ageTxt = document . createTextNode ( age );var dropButton = document . createElement ( "input" );dropButton . setAttribute ( "type" , "button" );dropButton . setAttribute ( "value" , "删除" );dropButton . setAttribute ( "onclick" , "_del(this);" );// 逐级添加unameTd . appendChild ( unameTxt );emailTd . appendChild ( emailTxt );ageTd . appendChild ( ageTxt );dropTd . appendChild ( dropButton );trNode . appendChild ( unameTd );trNode . appendChild ( emailTd );trNode . appendChild ( ageTd );trNode . appendChild ( dropTd );tablenode . appendChild ( trNode );}function _del ( obj ) {// 找到tr节点var trNode = obj . parentNode . parentNode ;// 使用tr节点的父节点,删除tr节点trNode . parentNode . removeChild ( trNode );}
7.2 使用HTML DOM方法
function _addTR () {var tablenode = document . getElementById ( "tabInfo" );var uname = document . getElementById ( "username" ). value ;var email = document . getElementById ( "email" ). value ;var age = document . getElementById ( "age" ). value ;// 创建一行var trNode = tablenode . insertRow ();// 创建一个单元格var unameTd = trNode . insertCell ();var emailTd = trNode . insertCell ();var ageTd = trNode . insertCell ();var dropTd = trNode . insertCell ();// 为单元格添加内容unameTd . innerHTML = uname ;emailTd . innerHTML = email ;ageTd . innerHTML = age ;dropTd . innerHTML = "<input type='button' οnclick='_del(this)' value='删除' />" ;}function _del ( obj ) {// 拿到table节点var tablenode = document . getElementById ( "tabInfo" );// 找到tr节点var trNode = obj . parentNode . parentNode ;// 使用HTML DOM的deleteRow方法tablenode . deleteRow ( trNode . rowIndex );}
当然,也可以全部用innerHTML来实现[IE10+]:
function _addTR () {var tablenode = document . getElementById ( "tabInfo" );var uname = document . getElementById ( "username" ). value ;var email = document . getElementById ( "email" ). value ;var age = document . getElementById ( "age" ). value ;// 使用innerHTML添加全部内容tablenode . innerHTML += "<tr><td>" + uname + "</td><td>" + email + "</td><td>" + age + "</td><td><input type='button' οnclick='_del(this)' value='删除' /></td></tr>" ;}
效果:
8. 全选/全不选/反选
HTML:
<!DOCTYPE html><html><head><meta charset = "utf-8" /><title> 添加节点 </title><script type = "text/javascript" src = "js.js" ></script></head><body><h1> 请选择你的爱好: </h1><label for = "all" > 全选/全不选 </label><input id = "all" type = "checkbox" name = "hobbys" onclick = " _chkSelectAll ( this . checked ) " /><br/><input id = "foot" type = "checkbox" name = "hobby" value = "football" /><label for = "foot" > 足球 </label><input id = "bask" type = "checkbox" name = "hobby" value = "basketball" /><label for = "bask" > 篮球 </label><input id = "swim" type = "checkbox" name = "hobby" value = "swim" /><label for = "swim" > 游泳 </label><input id = "sing" type = "checkbox" name = "hobby" value = "singing" /><label for = "sing" > 唱歌 </label><br/><input type = "button" value = "全选" onclick = " _chkSelectAll ( true ) " /><input type = "button" value = "全不选" onclick = " _chkSelectAll ( false ) " /><input type = "button" value = "反选" onclick = " _reverseChecked () " /></body></html>
JavaScript[HTML DOM方法]:
function _chkSelectAll ( chk ) {//拿到所有名字为hobby的checkbox对象var hobbyarr = document . getElementsByName ( "hobby" );for ( var i = 0 ; i < hobbyarr . length ; i ++) {hobbyarr [ i ]. checked = chk ;}}function _reverseChecked () {//拿到所有名字为hobby的checkbox对象var hobbyarr = document . getElementsByName ( "hobby" );for ( var i = 0 ; i < hobbyarr . length ; i ++) {hobbyarr [ i ]. checked = ! hobbyarr [ i ]. checked ;}}
效果:
9. 下拉列表左右移动
HTML:
<!DOCTYPE html><html><head><meta charset = "utf-8" /><title> 替换节点内容 </title><script type = "text/javascript" src = "js.js" ></script></head><body><table align = "center" ><tr><td><select size = "10" id = "left" ><option> 选项1 </option><option> 选项2 </option><option> 选项3 </option><option> 选项4 </option><option> 选项5 </option><option> 选项6 </option><option> 选项7 </option><option> 选项8 </option></select></td><td><input type = "button" value = "-> " οnclick="_removeLeft()" /><br/><input type = "button" value = "=> " οnclick="_removeLeftAll()" /><br/></td><td><select size = "10" id = "right" ><option> 选项9 </option></select></td></tr></table></body></html>
9.1 使用XML DOM的childNodes属性
function _removeLeft () {var leftSel = document . getElementById ( "left" );var rightSel = document . getElementById ( "right" );var optIdx = leftSel . selectedIndex ;// 使用XML DOM的childNodes属性需注意暗部的避免。// 这里使用变量count记录真正的选项索引,i为包括暗部的索引。var count = 0 ;var i = 0 ;while ( i < leftSel . childNodes . length ) {if ( leftSel . childNodes [ i ]. nodeType == 1 ) {if ( count == optIdx ) {var optNode = leftSel . childNodes [ i ];break ;}count ++;}i ++;}rightSel . appendChild ( optNode );}function _removeLeftAll () {// 拿到左右两侧下拉列表对象var leftSel = document . getElementById ( "left" );var rightSel = document . getElementById ( "right" );// 遍历左侧下拉列表项// 这里使用XML DOM的childNodes属性,会将所有的暗部一并添加到右侧while ( leftSel . childNodes . length > 0 ) {rightSel . appendChild ( leftSel . childNodes [ 0 ]);}}
9.2 使用HTML DOM的options属性和add方法
function _removeLeft () {var leftSel = document . getElementById ( "left" );var rightSel = document . getElementById ( "right" );// 获取选中的索引号var optIdx = leftSel . selectedIndex ;var optNode = leftSel . options [ optIdx ];// 将对应索引号的项添加到右边rightSel . add ( optNode );}function _removeLeftAll () {var leftSel = document . getElementById ( "left" );var rightSel = document . getElementById ( "right" );// 只要左边列表不为空,就将列表的第一项加到右边while ( leftSel . options . length > 0 ) {rightSel . add ( leftSel . options [ 0 ]);}}
效果:
HTML DOM之CSS(style)属性的使用
1. 概述
CSS样式对象均在HTML DOM节点的style属性中设置,具体可以查看相关文档。
2. 案例
颜色切换
<!DOCTYPE html><html><head><meta charset = "utf-8" /><title> 颜色切换 </title></head><body><span id = "a" style = " background - color : blue " > haha </span><span id = "b" style = " background - color : red " > hehe </span><script type = "text/javascript" >var b = false ;function _func () {b = ! b ;if ( b ) {document . getElementById ( "a" ). style . backgroundColor = "red" ;document . getElementById ( "b" ). style . backgroundColor = "blue" ;} else {document . getElementById ( "b" ). style . backgroundColor = "red" ;document . getElementById ( "a" ). style . backgroundColor = "blue" ;}}var inter = setInterval ( _func , 1000 );</script></body></html>
效果
漂浮广告
<!DOCTYPE html><html><head><meta charset = "utf-8" /><title> 漂浮广告 </title><script type = "text/javascript" >function _rand (){var randx = Math . random () * screen . width ;var randy = Math . random () * screen . height - 50 ;var tar = document . getElementById ( 'img' ). style ;tar . top = randy + "px" ;tar . left = randx + "px" ;}setInterval ( _rand , 500 );</script></head><body><span> 漂浮广告演示 </span><img src = "piaofu.jpg" id = "img" width = "50px" height = "50px" style = " position : absolute " /></body></html>