1、DOM 简介
当页面加载时,浏览器会创建页面的文档对象模型(Document Object Model)。文档对象模型定义访问和处理 HTML 文档的标准方法。DOM 将 HTML 文档呈现为带有元素、属性和文本的树结构,即节点树。通过 DOM,JS 可创建动态的 HTML,可以使网页显示动态效果并实现与用户的交互功能。JS 能够改变页面中所有的 HTML 元素、属性和 CSS 样式,并对页面中所有事件做出响应。所以学习 JS 的起点就是处理网页,处理网页就需要使用 DOM 进行操作。
2、DOM 获取元素
JS 要想操作 HTML 元素,那么首先就必须先找到该元素。通常使用以下几种方法完成:
通过元素设置的 id 找到 HTML 元素。
通过标签名找到 HTML 元素。
通过元素设置的名称 (name) 找到 HTML 元素。
所谓的 DOM,实际上就是 document,获取元素就是操作 document。
(1)、通过 id 找到元素
方法:document.getElementById('id');
网页是由标签将信息组合起来的,id 属性值是唯一的,就像身份证一样,通过一个身份证可以找到相对应的人,所以通过该方法,可以获取到与之相对应的标签,而获取的元素在 JS 中是一个对象,若想对元素进行操作,则需要通过他的属性或方法。
(2)、通过标签名找到元素
方法:document.getElementsByTagName('Tagname');
通过该方法,返回的是带有指定标签名的对象的集合,也就是以数组的形式返回,返回的顺序是他们在文档中的顺序。
(3)、通过 name 找到元素
方法:document.getElementsByName('name');
该方法与 getElementById() 方法有点相似,都是通过设置的属性值找到元素,只不过该方法是通过设置的 name 属性值查找元素。name 属性在文档中可能不唯一,所以该方法返回的也是元素的数组,而不是一个元素。
1 <body> 2 <input name="txt" type="text" value="1"> 3 <input name="txt" type="text" value="2"><br> 4 <input name="txt" type="text" value="3"> 5 <input name="txt" type="text" value="4"><br> 6 <input name="txt" type="text" value="5"> 7 <input name="aaa" type="text" value="6"> 8 <script> 9 //获取所有name值为txt的元素 10 var oTxt = document.getElementsByName("txt"); 11 12 //获取元素的个数 13 alert(oTxt.length); //返回:5 14 15 //获取第二个元素的值 16 alert(oTxt[1].value); //返回:2 17 </script> 18 </body>
既然可以通过 id 找到元素,那么也就可以通过 class 找到元素。className 属性用于设置或者返回元素的 class 类名。
语法:object.className = 'className'
该方法可以控制 class 类名,返回元素的 class 属性,作用是可以为网页中某个元素指定一个 className 来更改该元素的外观。
实例:简单的网页换肤效果
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8"> 5 <title>网页换肤</title> 6 <style> 7 body{ 8 background:lightgreen; 9 } 10 .col1{ 11 background:lightgray; 12 } 13 .col2{ 14 background:lightblue; 15 } 16 .col3{ 17 background:violet; 18 } 19 .col4{ 20 background:pink; 21 } 22 .col5{ 23 background:#f93; 24 } 25 </style> 26 </head> 27 <body id="boy"> 28 点击切换:<input type="button" value="灰色" onclick="gr()"> 29 <input type="button" value="蓝色" onclick="bl()"> 30 <input type="button" value="紫色" onclick="vi()"> 31 <input type="button" value="粉色" onclick="pi()"> 32 <input type="button" value="橘色" onclick="or()"> 33 <script> 34 var x = document.getElementById('boy'); 35 function gr(){ 36 x.className = 'col1'; 37 } 38 39 function bl(){ 40 x.className = 'col2'; 41 } 42 43 function vi(){ 44 x.className = 'col3'; 45 } 46 47 function pi(){ 48 x.className = 'col4'; 49 } 50 51 function or(){ 52 x.className = 'col5'; 53 } 54 </script> 55 </body> 56 </html>
这只是一个简单的切换背景色效果,如果想切换网页的整体样式,可以使用外部 CSS 文件,通过 JS 改变 link 标签的 href 属性来完成。
如果想设置多个 class 类名相同的元素的样式,就需要借助数组的方法来完成,其实现原理也很简单,首先通过 id 获取其父元素,再获取父元素下所有子元素的标签名,获取标签名返回的是元素的数组,所以就可以和访问数组一样的方法来访问元素的数组,那么先使用循环遍历该元素数组,再做判断,如果这个元素的 className 等于我们设置的 class 属性值,就说明这是我们要找的元素。
实例:将有序列表中所有 class 属性值为"col"的元素背景颜色设置为绿色
1 <body> 2 <ol id="o1"> 3 <li>热点</li> 4 <li class="col">美食</li> 5 <li>数码</li> 6 <li class="col">科技</li> 7 <li>社会</li> 8 <li class="col">养生</li> 9 </ol> 10 <script> 11 //通过id获取父元素 12 var aOl = document.getElementById('o1'); 13 //通过标签名获取父元素下所有子元素 14 var oLi = aOl.getElementsByTagName('li'); 15 //循环遍历返回的子元素数组 16 for(var i=0; i<oLi.length; i++){ 17 //如果当前子元素的className等于设置的class属性值,则将其背景设置为绿色 18 if(oLi[i].className == 'col') oLi[i].style.background = 'green'; 19 } 20 </script> 21 </body>
下面是一个通过 class 属性值获取元素的封装函数,方便以后使用。
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8"> 5 <title>封装getByClass函数</title> 6 <script> 7 //第一个参数为获取的父元素,第二个参数为class属性值。 8 function getByClass(oParent,aClass){ 9 //空数组可以把找到的所有className都存放在里边,最后返回。 10 var aResult = []; 11 //通过标签名获取父元素下所有子元素。标签名不固定,所以设置为*,便于传入。 12 var aEle = oParent.getElementsByTagName('*'); 13 //循环遍历返回的子元素数组 14 for(var i=0; i<aEle.length; i++){ 15 //如果当前子元素的className等于传入的class属性值,则将其添加到数值中。 16 if(aEle[i].className == aClass) aResult.push(aEle[i]); 17 } 18 //最后将这个数组返回 19 return aResult; 20 } 21 </script> 22 </head> 23 <body> 24 <ol id="o1"> 25 <li>热点</li> 26 <li class="col">美食</li> 27 <li>数码</li> 28 <li class="col">科技</li> 29 <li>社会</li> 30 <li class="col">养生</li> 31 </ol> 32 <script> 33 //封装函数的使用: 34 //先通过id获取父元素 35 var aOl = document.getElementById('o1'); 36 //再调用封装好的函数传入参数,获取的父元素,子元素的class属性值 37 var oCol = getByClass(aOl,'col'); 38 //最后循环遍历,设置样式 39 for(var i=0; i<oCol.length; i++){ 40 oCol[i].style.background = 'green'; 41 } 42 </script> 43 </body> 44 </html>
3、DOM操作
获取到 HTML 元素之后,就可以进行相应的操作。
(1)、改变HTML
修改 HTML 内容的最简单的方法时使用 innerHTML 属性。innerHTML 顾名思义,inner 就是内部的,既然是 HTML,那么就可以给里边放 HTML。该属性可用于获取和替换 HTML 元素的内容。
语法:document.getElementById(id).innerHTML = new HTML
1 <body> 2 <h1 id="tit">原标题</h1> 3 <script> 4 //改变原有标题 5 var aH = document.getElementById('tit'); 6 aH.innerHTML = '新标题'; 7 </script> 8 9 <div id="div1" style="width:500px;height:200px;border:1px solid black;"></div> 10 <script> 11 //创建HTML内容 12 var oDiv = document.getElementById('div1'); 13 oDiv.innerHTML = '<h2>我是h2标题</h2><p>我是一个段落</p>'; 14 </script> 15 </body>
(2)、操作元素属性
修改元素属性最简单的方法就是直接修改,语法:document.getElementById(id).属性名 = new value 比如修改图片src属性的指向路径。
此外还可以通过DOM方法获取、添加、删除元素的属性。
①、getAttribute()
getAttribute() 方法通过元素节点的属性名获取属性的值。
语法:elementNode.getAttribute(name) name是想要获取的元素节点的属性名
②、setAttribute()
setAttribute() 方法添加一个新属性并指定值,或者把一个现有的属性设定为指定的值。
语法:elementNode.setAttribute(name,value) name是属性名,value是属性值。
③、removeAttribute()
removeAttribute() 方法可删除元素的属性。
语法:elementNode.removeAttribute(name) name是属性名。
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8"> 5 <title>JavaScript实例</title> 6 </head> 7 <body> 8 <input id="txt1" type="text"> 9 <input id="btn1" type="button" value="按钮"> 10 <script> 11 var oTxt = document.getElementById('txt1'); 12 var oBtn = document.getElementById('btn1'); 13 14 //获取按钮value属性的值 15 var a = oBtn.getAttribute('value'); 16 alert(a); //返回:按钮 17 18 oBtn.onclick = function (){ 19 //操作元素属性有三种方法: 20 //第一种方法 21 //oTxt.value='请输入文字'; 22 23 //第二种方法 24 //oTxt['value']='请输入文字'; 25 26 //第三种方法 27 //修改文本框value属性的值 28 oTxt.setAttribute('value','请输入文字'); 29 30 //删除按钮type属性 31 oBtn.removeAttribute('type'); 32 //删除后默认为文本框 33 }; 34 </script> 35 </body> 36 </html>
(3)、改变CSS
改变 HTML 元素的 CSS 样式可直接使用该语法:document.getElementById(id).style.样式名 = new style
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8"> 5 <title>JavaScript实例</title> 6 <style> 7 #div1{ 8 height:400px; 9 width:600px; 10 border:1px solid black; 11 padding:5px; 12 } 13 p{ 14 line-height:18px; 15 text-indent:2em; 16 } 17 </style> 18 </head> 19 <body> 20 <h2>HTML DOM</h2> 21 <div id="div1"> 22 <h3>JS可以使网页添加动态效果并实现与用户交互的功能。</h3> 23 <p>1. JS能够改变页面中所有的 HTML 元素。</p> 24 <p>2. JS能够改变页面中所有的 HTML 属性。</p> 25 <p>3. JS能够改变页面中所有的 HTML 元素的CSS样式。</p> 26 </div> 27 28 <input type="button" value="改变颜色" onclick="color()"> 29 <input type="button" value="改变宽高" onclick="hig()"> 30 <input type="button" value="隐藏内容" onclick="none()"> 31 <input type="button" value="显示内容" onclick="block()"> 32 <input type="button" value="取消设置" onclick="cancel()"> 33 34 <script> 35 var oDiv = document.getElementById('div1'); 36 function color(){ 37 oDiv.style.color = 'white'; 38 oDiv.style.fontFamily = 'Microsoft YaHei'; 39 oDiv.style.backgroundColor = 'green'; 40 } 41 42 function hig(){ 43 oDiv.style.width = '400px'; 44 oDiv.style.height = '300px'; 45 oDiv.style.border = '5px solid #ccc'; 46 } 47 48 function none(){ 49 oDiv.style.display = 'none'; 50 } 51 52 function block(){ 53 oDiv.style.display = 'block'; 54 } 55 56 //取消设置 57 function cancel(){ 58 var clean = confirm('确定取消所有设置?'); 59 if(clean == true){ 60 oDiv.removeAttribute('style'); 61 } 62 } 63 </script> 64 </body> 65 </html>
上面的代码,通过 style 设置的样式,都是行间样式,可以使用火狐的 Firebug 点击相应的按钮,就能看到所有设置的 CSS 样式都出现在了行间。
可以直接通过 style 获取和设置 CSS 样式,那么有没有更简洁的方法呢?可以借助于函数使用 JS 的内置对象 arguments 完成,所谓 arguments,就是可变参,不定参,参数的个数可变,是一个参数数组,无需指出参数名,就可访问他们,但是为了增强可读性,给参数取名,还是很有必要的。
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8"> 5 <title>JavaScript实例</title> 6 </head> 7 <body> 8 <div id="div1" style="width:200px;height:200px;background:red"></div> 9 <script> 10 //获取行间样式 11 function css(){ 12 //如果传入参数的个数等于2 13 if(arguments.length == 2){ 14 //则返回第二个参数样式名的值 15 return arguments[0].style[arguments[1]]; 16 } 17 else{ 18 //否则就是设置CSS样式 19 //第二个参数样式名的值就等于传入的第三个参数 20 arguments[0].style[arguments[1]] = arguments[2]; 21 } 22 } 23 24 var oDiv = document.getElementById('div1'); 25 alert(css(oDiv,'width')); //获取对象的宽 返回:200px 26 css(oDiv,'background','green'); //将对象的背景颜色改为绿色 27 </script> 28 </body> 29 </html>
下面是一个获取和设置行间样式的封装函数,以便以后使用。
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8"> 5 <title>获取行间样式</title> 6 <script> 7 function css(obj, name, value){ 8 if(arguments.length == 2){ 9 return obj.style[name]; 10 } 11 else{ 12 obj.style[name] = value; 13 } 14 } 15 </script> 16 </head> 17 <body> 18 <div id="div1" style="width:200px;height:200px;background:red"></div> 19 <script> 20 var oDiv = document.getElementById('div1'); 21 alert(css(oDiv,'width')); //获取div的宽 22 css(oDiv,'background','green'); //设置div的背景颜色 23 </script> 24 </body> 25 </html>
我们都知道,在实际的 Web 项目开发中,要遵循结构、表现、行为相分离的原则,以增强可读性,优化代码,便于后期维护。所以通常我们设置元素的样式,并非都是在行间设置。使用 style 方法获取的只是 DOM 元素 style 属性里的样式规则,对于通过 class 属性设置的外部样式表,style 就显得力不从心了。那要如何获取元素的非行间样式呢?DOM 标准中有个全局方法 getComputedStyle,通过该方法可以获取当前对象的样式信息。比如:getComputedStyle(obj, false).paddingLeft,可以获取到对象的左内边距。这里需要注意:在获取元素的复合样式时,一定要使用精确的值,复合样式比如 background、border,如果要获取元素的背景颜色,只使用 background 会出错,一定要写成 backgroundColor。
JS 只能修改元素的行间样式,并不能修改获取到的非行间样式。那么很多人可能会产生疑问,既然可以获取到又不能修改,那还获取有什么用。其实获取非行间样式是非常有必要的,如果是外部样式表,样式都是密密麻麻一片英文的存在,不可能一个个去找,到底该元素设置的什么样子,再回头修改,那岂不是太浪费精力了,所以该方法就显得尤为重要,而且返回的值都是精确值,通过获取的非行间样式信息,也有利于更精细的修改元素的当前样式,这是多么美妙的一件事,直接使用 style 设置元素的行间样式,因为行间样式的优先级最高,所以就覆盖掉了非行间样式,其实也就相当于跟修改了非行间样式一样,只是显示在了行间,我们的目的反着是已经达到了。
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8"> 5 <title>获取非行间样式</title> 6 <style> 7 #div1{ 8 width:200px; 9 height:200px; 10 background:red; 11 margin-top:10px; 12 } 13 </style> 14 <script> 15 window.onload = function (){ 16 var oDiv = document.getElementById('div1'); 17 18 alert(getComputedStyle(oDiv,false).width); 19 oDiv.style.width = '400px'; 20 21 alert(getComputedStyle(oDiv,false).height); 22 oDiv.style.height = '400px'; 23 24 //注意这里修改复合样式时,使用的background,可在FF下用Firebug查看具体的行间样式。 25 alert(getComputedStyle(oDiv,false).backgroundColor); 26 oDiv.style.background = 'green'; 27 }; 28 </script> 29 </head> 30 <body> 31 <div id="div1"></div> 32 </body> 33 </html>
(4)、对事件做出响应
实例:全选和反选,输入对应的序号选中
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8"> 5 <title>JavaScript实例</title> 6 </head> 7 <body> 8 <form id="list"> 9 请选择你的业余爱好:<br> 10 1. 音乐<input type="checkbox" name="love" id="like1"> 11 2. 阅读<input type="checkbox" name="love" id="like2"> 12 3. 游泳<input type="checkbox" name="love" id="like3"> 13 4. 篮球<input type="checkbox" name="love" id="like4"> 14 5. 足球<input type="checkbox" name="love" id="like5"> 15 6. 散步<input type="checkbox" name="love" id="like6"> 16 7. 泡吧<input type="checkbox" name="love" id="like7"> 17 8. 逛街<input type="checkbox" name="love" id="like8"><br> 18 <input type="button" value = "全选" onclick="optAll()"> 19 <input type="button" value = "反选" onclick="noAll()"> 20 21 <p>输入1-8序号选择,每次只可以选择一项:</p> 22 <input id="txt1" type="text"> 23 <input id="btn1" type="button" value="确定"> 24 </form> 25 <script> 26 function optAll(){ 27 //通过获取标签名设置全选 28 var oList = document.getElementById('list'); 29 var aCheck = oList.getElementsByTagName('input'); 30 for(var i=0; i<aCheck.length; i++){ 31 if(aCheck[i].type == 'checkbox'){ 32 aCheck[i].checked = true; 33 } 34 } 35 } 36 37 function noAll(){ 38 //通过获取设置的name属性值设置反选 39 var aLove = document.getElementsByName('love'); 40 for(var i=0; i<aLove.length; i++){ 41 if(aLove[i].type == 'checkbox'){ 42 aLove[i].checked = false; 43 } 44 } 45 } 46 47 var oBtn = document.getElementById('btn1'); 48 //给获取的按钮添加点击事件 49 oBtn.onclick = function (){ 50 //获取文本框输入的值 51 var oTxt = document.getElementById("txt1").value; 52 //定义的复选框id值为like1-8。括号中进行的是字符串连接,id+输入到文本框的值=该元素的id值 53 var oLike = document.getElementById('like' + oTxt); 54 oLike.checked = true; 55 } 56 </script> 57 </body> 58 </html>
3、DOM节点
HTML 文档可以说是由节点构成的集合,常见的 DOM 节点有三种,即元素节点、属性节点和文本节点。元素节点就是 HTML 标签,标签的属性就是属性节点,文本节点就是页面可以浏览的内容。
在文档对象模型中,每一个节点都是一个对象,DOM 节点有三个重要的属性:节点的名称,节点的值和节点的类型。
(1)、nodeName:节点的名称
nodeName 属性返回节点的名称。元素节点的名称与标签名相同(大写),属性节点的名称是属性的名称,文本节点的名称永远都是 #text,文档节点的名称永远都是 #document。
(2)、nodeValue:节点的值
nodeValue 属性返回节点的值。元素节点的值是 undegined 或 null,属性节点的值是属性的值,文本节点的值是文本自身。
(3)、nodeType:节点的类型
nodeType 属性返回节点的类型。以下是常见的节点类型:
节点类型 | 说明 | 值 |
元素节点 | 每一个HTML标签都是一个元素节点,如 <div> 、 <p>、<ul>等 | 1 |
属性节点 | 元素节点(HTML标签)的属性,如 id 、class 、name 等。 | 2 |
文本节点 | 元素节点或属性节点中的文本内容。 | 3 |
注释节点 | 表示文档注释,形式为<!-- text content -->。 | 8 |
文档节点 | 表示整个文档(DOM 树的根节点,即 document )。 | 9 |
综合实例:
1 <body> 2 <ul> 3 <li>JS</li> 4 <li>DOM</li> 5 </ul> 6 <script> 7 var nodes = document.getElementsByTagName('li'); 8 for(var i=0; i<nodes.length; i++){ 9 document.write('第' + (i+1) + '个节点的名称是' + nodes[i].nodeName + '<br>'); 10 document.write('第' + (i+1) + '个节点的值是' + nodes[i].nodeValue + '<br>'); 11 document.write('第' + (i+1) + '个节点的类型是' + nodes[i].nodeType + '<br>'); 12 document.write('<br>'); 13 } 14 15 /* 16 返回: 17 第1个节点的名称是LI 18 第1个节点的值是null 19 第1个节点的类型是1 20 21 第2个节点的名称是LI 22 第2个节点的值是null 23 第2个节点的类型是1 24 */ 25 </script> 26 </body>
JS 中函数可以嵌套使用,有父函数有子函数,HTML 标签也可以嵌套使用,那么就说明存在着各种不同的节点关系,比如父节点、子节点和兄弟节点。为了方便操作,DOM定义了一些节点的公共属性。
(1)、子节点
childNodes 属性返回节点的子节点集合,可使用length属性返回子节点的数量,然后就可以和数组一样获取需要的信息。
1 <body> 2 <ul id="u1"> 3 <li>1</li> 4 <li>2</li> 5 <li>3</li> 6 <li>4</li> 7 <li>5</li> 8 </ul> 9 <script> 10 var oUl = document.getElementById('u1'); 11 alert(oUl.childNodes.length); //返回:11 12 </script> 13 </body>
通过上面的代码,可以看到返回的是 11。ul 下明明只有 5 个 li 元素,怎么会返回 11 呢?其实是这么回事:
1 <ul id="u1"> 第1个节点(文本节点) 2 <li>第2个节点(元素节点)</li> 第3个节点(文本节点) 3 <li>第4个节点(元素节点)</li> 第5个节点(文本节点) 4 <li>第6个节点(元素节点)</li> 第7个节点(文本节点) 5 <li>第8个节点(元素节点)</li> 第9个节点(文本节点) 6 <li>第10个节点(元素节点)</li> 第11个节点(文本节点) 7 </ul>
因为通过 childNodes 属性返回的子节点集合,不仅包括元素节点,而且还包括文本节点,浏览器会将标签之间的空白默认为文本节点,如果在空白处输入文字,就会显示在页面上,这就造成了不必要的麻烦,所以建议使用 children 属性,该属性只返回元素节点,不包括文本节点,并且不包括注释节点。
1 <body> 2 <ul id="u1"> 3 <li> 4 我是个文本节点 5 <span>我是span元素。</span> 6 </li> 7 <li></li> <!-- 注释 --> 8 <li></li> 9 <li></li> 10 <li></li> 11 </ul> 12 <script> 13 var oUl = document.getElementById('u1'); 14 alert(oUl.children.length); //返回:5 15 </script> 16 </body>
上面的代码,ul 下有 5 个 li 元素,返回子节点个数为 5。children 属性要比 childNodes 属性好用太多了,只返回元素的子节点,还不包括孙子辈节点。
(2)、首尾子节点
firstElementChild 属性返回 children 数组的第一个节点。
语法:node.firstElementChild 该方法相当于:element.children[0]
lastElementChild 属性返回 children 数组的最后一个节点。
语法:node.lastElementChild 该方法相当于:element.children[element.children.length-1]
1 <body> 2 <div style="border:2px solid green" id="div1"> 3 空白节点 4 <p>JS</p> 5 <div>DOM</div> 6 <h3>jQuery</h3> 7 </div> 8 <script> 9 var x = document.getElementById('div1'); 10 document.write('第一个节点的名称:' + x.firstElementChild.nodeName + '<br>'); 11 //返回:第一个子节点的名称:P 12 document.write('最后一个节点的名称:' + x.lastElementChild.nodeName) 13 //返回:最后一个子节点的名称:H3 14 </script> 15 </body>
(3)、父节点
parentNode 属性用于获取指定节点的父节点。注意:父节点只能有一个。通过使用两个获取父节点,可获取祖节点。
实例:点击子节点,隐藏父节点
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8"> 5 <title>JavaScript实例</title> 6 </head> 7 <body> 8 <ul id="u1"> 9 <li>aaa <a href="javascript:;">点击隐藏</a></li> 10 <li>bbb <a href="javascript:;">点击隐藏</a></li> 11 <li>ccc <a href="javascript:;">点击隐藏</a></li> 12 <li>ddd <a href="javascript:;">点击隐藏</a></li> 13 <li>eee <a href="javascript:;">点击隐藏</a></li> 14 </ul> 15 <script> 16 var oUl = document.getElementById('u1'); 17 //查看ul元素的父节点 18 alert(oUl.parentNode); //返回:[object HTMLBodyElement] 19 20 //通过标签名获取所有的a元素 21 var aA = document.getElementsByTagName('a'); 22 for(var i=0; i<aA.length; i++){ 23 aA[i].onclick = function (){ 24 //设置当前节点的父节点为隐藏 25 this.parentNode.style.display = 'none'; 26 }; 27 } 28 </script> 29 </body> 30 </html>
offsetParent 属性可返回一个元素用于定位的父级。
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8"> 5 <title>JavaScript实例</title> 6 <style> 7 #div1{ 8 width:200px; 9 height:200px; 10 background:green; 11 margin:100px; 12 /*position:relative;*/ 13 } 14 #div2{ 15 width:100px; 16 height:100px; 17 background:red; 18 position:absolute; 19 left:50px; 20 top:50px; 21 } 22 </style> 23 </head> 24 <body> 25 <div id="div1"> 26 <div id="div2"></div> 27 </div> 28 <script> 29 var oDiv2 = document.getElementById('div2'); 30 alert(oDiv2.offsetParent); 31 //返回:[object HTMLBodyElement] 32 33 //div2的父级是div1,如果取消div1相对定位的注释。则返回:[object HTMLDivElement] 34 </script> 35 </body> 36 </html>
(3)、兄弟节点
nextElementSibling 属性返回同一树层级中某个节点之后紧跟的节点。
语法:element.nextElementSibling
previousElementSibling 属性返回同一树层级中某个节点之前紧跟的节点。
语法:element.previousElementSibling
实例:获取 li 元素节点的兄弟节点
1 <body> 2 <ul> 3 <li>HTML</li> 4 <li>CSS</li> 5 <li>JS</li> 6 </ul> 7 <script> 8 var aLi = document.getElementsByTagName('li'); 9 //获取第二个子节点之后紧跟的节点 10 var x = aLi[1].nextElementSibling; 11 alert(x.innerHTML); //返回:JS 12 13 //获取第二个子节点之前紧跟的节点 14 var y = aLi[1].previousElementSibling; 15 alert(y.innerHTML); //返回:HTML 16 </script> 17 </body>
4、DOM 应用
DOM 最实际的应用就是可以通过 JS 创建、插入和删除节点。
(1)、创建节点
createElement() 方法可创建元素节点。
语法:document.createElement(tagName)
appendChild()方法可在指定节点的末尾插入一个新的子节点,每次都向末尾添加。
语法:父级.appendChild(new node)
实例:创建并添加 li 元素
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8"> 5 <title>JavaScript实例</title> 6 <script> 7 window.onload = function (){ 8 var oBtn = document.getElementById('btn1'); 9 var oUl = document.getElementById('u1'); 10 var oTxt = document.getElementById('txt1'); 11 12 //文本框输入提示 13 oTxt.placeholder = '请输入文字创建li元素'; 14 15 oBtn.onclick = function (){ 16 //创建li元素 17 var oLi = document.createElement('li'); 18 19 //创建的li元素的HTML=文本框输入的值 20 oLi.innerHTML = oTxt.value; 21 22 //插入到oUl父级下,作为子节点,在每个创建的li末尾插入新创建的li元素 23 oUl.appendChild(oLi); 24 //父级.appendCild(子节点); 25 }; 26 }; 27 </script> 28 </head> 29 <body> 30 <input id="txt1" type="text"value=""> 31 <input id="btn1" type="button"value="创建li"> 32 <ul id="u1"></ul> 33 </body> 34 </html>
(2)、插入节点
insertBefore() 方法可在已有的子节点前插入一个新的子节点。
语法:父级.insertBefore(new node, node) 第一个参数为要插入的新子节点。第二个参数是原有节点,也就是在谁之前插入。
实例:创建并添加 li 元素,每个新创建的 li 元素都插入到之前插入的 li 元素之前
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8"> 5 <title>JavaScript实例</title> 6 <script> 7 window.onload = function (){ 8 var oBtn = document.getElementById('btn1'); 9 var oUl = document.getElementById('u1'); 10 var oTxt = document.getElementById('txt1'); 11 12 oBtn.onclick = function (){ 13 //创建li元素 14 var oLi = document.createElement('li'); 15 //获取所有li元素 16 var aLi = oUl.getElementsByTagName('li'); 17 oLi.innerHTML = oTxt.value; 18 19 //这里需要注意:页面中本没有li元素,li元素是通过JS创建的 20 //所以第一个li元素应该添加到父级下最后一个子节点 21 //然后基于这个节点,将之后再插入的子节点插入到上一个节点之前 22 23 //如果li元素本来不存在,则执行else,在父级插入一个子节点。 24 //如果li元素的个数>0,说明已经创建了,则插入到这个子节点之前。 25 if(aLi.length>0){ 26 oUl.insertBefore(oLi,aLi[0]); 27 } 28 else{ 29 oUl.appendChild(oLi); 30 } 31 }; 32 }; 33 </script> 34 </head> 35 <body> 36 <input id="txt1" type="text" value=""> 37 <input id="btn1" type="button" value="创建li"> 38 <ul id="u1"></ul> 39 </body> 40 </html>
(4)、删除节点
removeChild() 方法用于删除一个节点
语法:父级.removeChild(node) 参数为要删除的子节点。
实例:简单的表格添加和删除
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8"> 5 <title>JavaScript实例</title> 6 <script> 7 window.onload = function (){ 8 var oTab = document.getElementById('tab1'); 9 var oName = document.getElementById('user'); 10 var oAge = document.getElementById('age'); 11 var oBtn = document.getElementById('btn1'); 12 13 //设置添加的ID项的值 14 var id = oTab.tBodies[0].rows.length+1; 15 16 oBtn.onclick = function (){ 17 //创建一个tr 18 var oTr = document.createElement('tr'); 19 //创建第一个td(ID项) 20 var oTd = document.createElement('td'); 21 //获取ID,已经删除的ID号,不能再重用。 22 oTd.innerHTML = id++; 23 //将创建的td放入创建的tr中 24 oTr.appendChild(oTd); 25 26 //创建第二个td(姓名项) 27 var oTd = document.createElement('td'); 28 oTd.innerHTML = oName.value; 29 oTr.appendChild(oTd); 30 31 //创建第三个td(年龄项) 32 var oTd = document.createElement('td'); 33 oTd.innerHTML = oAge.value; 34 oTr.appendChild(oTd); 35 36 //创建第四个td(操作项) 37 var oTd = document.createElement('td'); 38 oTd.innerHTML = '<a href="javascript:;">删除</a>'; 39 oTr.appendChild(oTd); 40 41 oTd.getElementsByTagName('a')[0].onclick = function (){ 42 //删除整行 43 oTab.tBodies[0].removeChild(this.parentNode.parentNode); 44 }; 45 46 //将创建好的tr放入tbody中 47 oTab.tBodies[0].appendChild(oTr); 48 }; 49 }; 50 </script> 51 </head> 52 <body> 53 姓名:<input id="user"type="text"> 54 年龄:<input id="age"type="text"> 55 <input id="btn1" type="button" value="添加"> 56 <table id="tab1" border="1" width="500px"> 57 <caption>员工表</caption> 58 <thead> 59 <tr> 60 <th>ID</th> 61 <th>姓名</th> 62 <th>年龄</th> 63 <th>操作</th> 64 </tr> 65 </thead> 66 <tbody> 67 <tr> 68 <td>1</td> 69 <td>小白</td> 70 <td>27</td> 71 <td></td> 72 </tr> 73 <tr> 74 <td>2</td> 75 <td>小明</td> 76 <td>25</td> 77 <td></td> 78 </tr> 79 <tr> 80 <td>3</td> 81 <td>小红</td> 82 <td>21</td> 83 <td></td> 84 </tr> 85 <tr> 86 <td>4</td> 87 <td>张三</td> 88 <td>29</td> 89 <td></td> 90 </tr> 91 <tr> 92 <td>5</td> 93 <td>李四</td> 94 <td>35</td> 95 <td></td> 96 </tr> 97 </tbody> 98 </table> 99 </body> 100 </html>
这个实例只能很简单的完成添加和删除,并不对输入进行判断,如果想要做的完美,还需要做很多工作,可以对表格进行美化,设置背景色,鼠标移入高亮显示,鼠标移出恢复背景色,最关键的就是要对表单输入内容进行判断,以确保每次提交的信息都是有效信息,如果表格信息量大,还可以添加支持模糊搜素,多关键字搜索,以提高用户体验度,当然在实际的项目中,这样的情况几乎不会出现,但可以作为自己的实践,检验学习成果。
(5)、替换节点和创建文本节点
replaceChild() 方法可用于替换元素节点。
语法:node.replaceChild (new node, node) 第一个参数为用于替换的节点。第二个参数为原有节点。
createTextNode() 方法可创建新的文本节点,返回新创建的 Text 节点。
语法:document.createTextNode(txt)
这两种方法平时几乎用不到,但还是需要了解。
实例:点击按钮将 span 标签替换为 b 标签。再创建一个文本节点插入到创建的 p 元素下,并设置 className
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8"> 5 <title>JavaScript实例</title> 6 <style> 7 .p1{ 8 width:300px; 9 height:100px; 10 background-color:#ccc; 11 } 12 </style> 13 </head> 14 <body> 15 <p>创建一个P标签,设置<span id="s">className</span>属性,创建文本节点。</p> 16 <input type="button" value="点击替换" onclick="change()"> 17 <script> 18 function change(){ 19 //获取span元素 20 var oS = document.getElementById('s'); 21 //创建一个b元素 22 var newNode = document.createElement('b'); 23 //要替换的文本节点 24 var txt = document.createTextNode('className'); 25 //将文本节点插入到创建的b元素下 26 newNode.appendChild(txt); 27 //在span元素的父级下将span元素替换成新创建的b元素 28 oS.parentNode.replaceChild(newNode,oS); 29 } 30 31 //创建一个p元素 32 var oP = document.createElement('p'); 33 //设置className 34 oP.className = 'p1'; 35 //创建文本节点 36 var txtNode = document.createTextNode('createTextNode用于创建文本节点!'); 37 //将创建的文本节点插入到p元素下 38 oP.appendChild(txtNode); 39 //再将p元素插入到父级body下 40 document.body.appendChild(oP); 41 </script> 42 </body> 43 </html>