[聚合文章] 【JavaScript从入门到精通】第十一课(程序员学习dom基础)

程序员 2017-11-21 13 阅读

第十一课 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符合要求的元素,最后将整个数组作为返回值返回。

注:本文内容来自互联网,旨在为开发者提供分享、交流的平台。如有涉及文章版权等事宜,请你联系站长进行处理。