第十一课 DOM 基础
在讲JS的时候,我们已经学过,JS是由ECMA,DOM,BOM三部分组成,这节课开始我们将深入学习DOM。
什么是DOM
DOM是JS一个重要组成部分,可以让JS可以操作页面上的元素。实际上,DOM在JS里是以document的形式体现的,所有对页面元素的操作都是通过document进行的。
首先来谈谈浏览器对DOM的支持性。目前主流的浏览器有3种:IE,Chrome和FF(火狐)。实际上,DOM除了是JS的一个组成部分外,也是一套规范,规定了浏览器如何去进行操作。在三种主流浏览器中,FF是最标准的浏览器,它对DOM有99%的支持性,而IE浏览器只有10%左右(IE9以后有了一定提升),Chrome浏览器则介于两者之间,有大概百分之60左右的支持性。
DOM节点
首先我们来看一个最基本的概念: 子节点 和 父节点 。 在下面一个例子:
<!DOCTYPE html><br /><html><br /> <head> <br /> <meta charset="utf-8" /> <br /> <title>无标题文档</title> <br /> </head> <br /> <body> <br /> <ul id="ul1"> <br /> <li></li> <br /> <li></li> <br /> </ul> <br /> </body><br /></html>
在这个例子中,ul就是li的父节点,body是ul的父节点;反过来说,每个li都是ul的子节点。那么,在JS里,我们要如何对节点进行操作呢?在JS里,选中子节点的方法是:childNodes。 childNodes本质上是个数组,数组里存放的内容就是父节点下的各子节点。现在我们来输出ul1中子节点的个数。
window.onload=function () { var oUl=document.getElementById('ul1'); alert(oUl.childNodes.length); }
结果如下:
很奇怪,为什么答案是5个而不是2个呢?因为在IE9下,childNodes会把空的文本节点也算为数组中的元素,也就是说<ul><li></li><li></li></ul>一共包含<ul><li>,<li></li>,</li><li>,<li></li>,</li></ul>这5个节点。不过如果使用IE6-8的浏览器就不会出现这个问题,会弹出正确答案2。
当我们想通过childNodes设置样式的时候,这个问题的严重性就会凸显出来,因为文本节点是没有style的,如果我们想给每个子节点设置样式,就会出现错误。为了解决这个问题,我们需要使用另一个属性:nodeType。通过nodeType可以判断节点的类型(其中,文本节点的值为3,元素节点的值为1),只对元素节点的样式进行设置,这样就可以达成我们的目的了。
window.onload=function () { var oUl=document.getElementById('ul1'); for(var i=0;i<oUl.childNodes.length;i++) { if(oUl.childNodes[i].nodeType==1) { oUl.childNodes[i].style.background='red'; } } };
实际上,比起childNodes,还有一种名为children的属性,它可以直接选中子节点的元素节点,比起使用childNodes+nodeType更为方便。
值得注意的是,子节点只算父节点下第一层的元素,如果子节点下还有子节点,是不会算入父节点的子节点中的。
同样的,我们也有操纵父节点的方法:parentNode。现在我们来看一个隐藏父元素的例子。
<html><br /> <head> <br /> <meta charset="utf-8" /> <br /> <title>无标题文档</title> <br /> <script><br /> window.onload=function ()<br /> {<br /> var aA=document.getElementsByTagName('a');<br /> <br /> for(var i=0;i<aA.length;i++)<br /> {<br /> aA[i].onclick=function ()<br /> {<br /> this.parentNode.style.display='none';<br /> };<br /> }<br /> };<br /> </script> <br /> </head> <br /> <body> <br /> <ul id="ul1"> <br /> <li>dfasdf <a href="javascript:;">隐藏</a></li> <br /> <li>45346 <a href="javascript:;">隐藏</a></li> <br /> <li>fghfgcvn <a href="javascript:;">隐藏</a></li> <br /> <li>vcbxcvbc <a href="javascript:;">隐藏</a></li> <br /> <li>757465867 <a href="javascript:;">隐藏</a></li> <br /> </ul> <br /> </body><br /></html>
效果如下:
点击隐藏a标签后,对应父元素被隐藏。
和parentNode类似的一个属性是offserParent,让我们对比以下两个例子:
<html><br /> <head> <br /> <meta charset="utf-8" /> <br /> <title>无标题文档</title> <br /> <style><br /> #div1 {width:200px; height:200px; background:#CCC; margin:100px; }<br /> #div2 {width:100px; height:100px; background:red; position:absolute; left:50px; top:50px;}<br /> </style> <br /> <script><br /> window.onload=function ()<br /> {<br /> var oDiv2=document.getElementById('div2');<br /> <br /> alert(oDiv2.offsetParent);<br /> };<br /> </script> <br /> </head> <br /> <body> <br /> <div id="div1"> <br /> <div id="div2"></div> <br /> </div> <br /> </body><br /></html>
效果如下:
<html><br /> <head> <br /> <meta charset="utf-8" /> <br /> <title>无标题文档</title> <br /> <style><br /> #div1 {width:200px; height:200px; background:#CCC; margin:100px; position:relative; }<br /> #div2 {width:100px; height:100px; background:red; position:absolute; left:50px; top:50px;}<br /> </style> <br /> <script><br /> window.onload=function ()<br /> {<br /> var oDiv2=document.getElementById('div2');<br /> <br /> alert(oDiv2.offsetParent);<br /> };<br /> </script> <br /> </head> <br /> <body> <br /> <div id="div1"> <br /> <div id="div2"></div> <br /> </div> <br /> </body><br /></html>
结果如下:
可以看到,二者的唯一区别在于div1的position属性,在第一个例子里,div1的positon属性为空,所以div2实际上是根据body来进行定位的,而第二个例子里div1的positon为relative,因此div2是根据div1来定位。而offsetParent的作用就是获取该元素用于定位的父级。
首位子节点和兄弟节点
这里介绍简单介绍一些DOM的基础操作和属性。
- firstChild,firstElementChild,获取元素的第一个子节点
- lastChild,lastElementChild,获取元素的最后一个子节点
- nextSibling,nextElementSibling,获取元素的上一个兄弟节点
- previousSibling,previousElementSibling,获取元素的下一个兄弟节点
这些方法都存在一定的兼容性问题,在高版本浏览器下firstChild与childNodes相同指的是第一个文本节点,因此我们需要用firstElementChild的方法才能选中其真正的第一个子节点。(其它操作也是如此)
设置属性的第三种方法
我们前面已经学习过oDiv.style.display=“block”和oDiv.style[“display”]=“block”这两种设置属性的方法,现在我们来学习第三种:Dom方式操作元素属性,这里我们采用的是这几个方法:
- getAttribute(名称),用于获取
- setAttribute(名称,值得),用于设置
- removeAttribute(名称),用于删除
className选择元素
过去我们选择元素都是使用id,虽然很精准,但元素过多的时候会很繁杂。后面我们又学习了使用标签名寻找元素,但精确度又差了一些。这里我们学习一种新的获取元素的方法:用class获取元素。使用class获取元素,有以下好处:1.可以批量化;2.可以具有选择性;3.页面发生变化时程序不会出现问题。
<html><br /> <head> <br /> <meta charset="utf-8" /> <br /> <title>无标题文档</title> <br /> <script><br /> window.onload=function ()<br /> {<br /> var oUl=document.getElementById('ul1');<br /> var aLi=oUl.getElementsByTagName('li');<br /> <br /> for(var i=0;i<aLi.length;i++)<br /> {<br /> if(aLi[i].className=='box')<br /> {<br /> aLi[i].style.background='red';<br /> }<br /> }<br /> };<br /> </script> <br /> </head> <br /> <body> <br /> <ul id="ul1"> <br /> <li class="box"></li> <br /> <li class="box"></li> <br /> <li></li> <br /> <li></li> <br /> <li></li> <br /> <li class="box"></li> <br /> <li></li> <br /> </ul> <br /> </body><br /></html>
效果如下:
凡是class为box的li背景颜色都变为了红色。通过class获取元素的原理非常简单,但是如果我们经常使用它,这种写法会显得非常复杂,因此我们打算把它封装成一个函数使用。
<html> <head> <meta charset="utf-8" /> <title>无标题文档</title> <script> function getByClass(oParent, sClass) { var aResult=[]; var aEle=oParent.getElementsByTagName('*'); for(var i=0;i<aEle.length;i++) { if(aEle[i].className==sClass) { aResult.push(aEle[i]); } } return aResult; } window.onload=function () { var oUl=document.getElementById('ul1'); var aBox=getByClass(oUl, 'box'); for(var i=0;i<aBox.length;i++) { aBox[i].style.background='red'; } }; </script> </head> <body> <ul id="ul1"> <li class="box"></li> <li class="box"></li> <li></li> <li></li> <li></li> <li class="box"></li> <li></li> </ul> </body> </html>
这其中需要注意的是,为了让函数具有更好的通用性,我们将getElementsByTagName的参数设为了*通配符,代表了所有标签,这样可以选取所有的元素。此外,我们在函数内定义了一个aResult数组,用于存放className符合要求的元素,最后将整个数组作为返回值返回。
注:本文内容来自互联网,旨在为开发者提供分享、交流的平台。如有涉及文章版权等事宜,请你联系站长进行处理。