JavaScript(十八):DOM对象

一世执手 提交于 2019-12-20 18:52:06

【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>

一、 认识DOM

DOM(Document Object Model,文档对象模型):定义访问和处理HTML文档的标准方法。DOMHTML 文档呈现为带有 元素、属性和文本的树结构(节点树)。

先来看看下面代码:

<!DOCTYPE HTML>
<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html;charset=gb2312"/>
		<title>DOM</title>
	</head>
	<body>
		<h2>
			<a href="http://www.imooc.com">javascript DOM</a>
		</h2>
		<p>
			对HTML元素进行操作,可添加、改变或移除CSS样式等
		</p>
		<ul>
			<li>JavaScript</li>
			<li>DOM</li>
			<li>CSS</li>
		</ul>
	</body>
</html>

HTML 代码分解为 DOM 节点层次图: 输入图片说明

文档构成:

HTML 文档可以说由 节点 构成的集合,DOM 节点有:

  1. 元素节点:上图中<html>、<body>、<p>等都是元素节点,即标签。

  2. 文本节点 :向用户展示的内容,如<li>...</li>中的JavaScript、DOM、CSS等文本。

  3. 属性节点: 元素属性,如<a>标签的链接属性href="http://www.imooc.com"。

看下面代码:

<a href="http://www.imooc.com">JavaScript DOM</a>

输入图片说明

二、元素节点获取方式

2.1、通过 ID 获取元素

学过HTML/CSS样式,都知道,网页由标签将信息组织起来,而标签的 id 属性值是唯一的,就像是每人有一个身份证号一样,只要通过身份证号就可以找到相对应的人。那么在网页中,我们通过id先找到标签,然后进行操作。

语法:

document.getElementById("id") 

看看下面代码:

<!DOCTYPE HTML>
<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html;charset=gb2312"/>
		<title>获取元素</title>
		<script type="text/javascript">
		  var mye = document.getElementById("con");//获取元素存储在变量mye中
		  document.write(mye);// 输出变量mye
		</script>
	</head>
	<body>
		<h3>Hello</h3>
		<p id="con">I love JavaScript</p>
	</body>
</html>

结果:null或[object HTMLParagraphElement] 输入图片说明

注:获取的元素是一个对象,如想对元素进行操作,我们要通过它的属性或方法。

2.2、 getElementsByName() 方法

返回带有指定名称的节点对象的集合。

语法

document.getElementsByName(name)

getElementById() 方法不同的是,通过元素的 name 属性查询元素,而不是通过id属性。

注意:

  • 因为文档中的 name 属性可能不唯一,所有 getElementsByName() 方法返回的是元素的数组,而不是一个元素。
  • 和数组类似也有 length 属性,可以和访问数组一样的方法来访问,从0开始。

看看下面的代码:

<!DOCTYPE HTML>
<html>
	<head>
		<script type="text/javascript">
		  function getElements(){
		     var x = document.getElementsByName("alink");
			 alert(x.length);
		  }
		</script>
	</head>
	<body>
		<a name="alink" href="#">我是链接一</a>
	    <a name="alink" href="#">我是链接二</a>
	    <a name="alink" href="#">我是链接三</a>
		<br />
		<input type="button" onclick="getElements()" value = "看看几个链接?" />
	</body>
</html>

运行结果:
输入图片说明

2.3、 getElementsByTagName() 方法

返回带有指定标签名的节点对象的集合。
返回元素的顺序是它们在文档中的顺序。


语法:

document.getElementsByTagName(Tagname)

说明:

  • Tagname 是标签的名称,如paimg等标签名。
  • 和数组类似也有length属性,可以和访问数组一样的方法来访问,所以从0开始。

看看下面代码,通过getElementsByTagName()获取节点。

<!DOCTYPE HTML>
<html>
	<head>
	    <title>JavaScript</title>
	</head>
	<body>
	    <p id="intro">我的课程</p>
		<ul>
		  <li>JavaScript</li>
		  <li>JQuery</li>
		  <li>HTML</li>
		  <li>JAVA</li>
		  <li>PHP</li>
		</ul>
		<script>
		  // 获取所有 li 集合
		  var list = document.getElementByTagName('li');
		  // 访问无序列表:[0]索引
		  li =  list[0];
		  // 获取 list 的长度
		  document.write(list.length);
		  // 弹出 li 节点对象的内容
		  document.write(li.innerHTML);
		</script>
	</body>
</html>

2.4、上述三种方式的区别

以人来举例说明,人有能标识身份的身份证,有姓名,有类别(大人、小孩、老人)等。

  • ID 是一个人的身份证号码,是唯一的。所以通过getElementById获取的是指定的一个人。

  • Name 是他的名字,可以重复。所以通过getElementsByName获取名字相同的人集合。

  • TagName可看似某类,getElementsByTagName获取相同类的人集合。如获取小孩这类人,getElementsByTagName("小孩")。

把上面的例子转换到HTML中,如下:

<input type="checkbox" name="hobby" id="hobby1">  音乐
  • input标签就像人的类别。

  • name属性就像人的姓名。

  • id属性就像人的身份证。


方法总结如下:

方法 说明 结果集
getElementById 通过指定 id 获得元素 1个
getElementsByName 通过元素名称 name 属性获得元素 1组
getElementsByTagName 通过标签名称获得元素 1组

**注意:**方法区分大小写


通过下面的例子(6个name="hobby"的复选项,两个按钮)来区分三种方法的不同:

  <input type="checkbox" name="hobby" id="hobby1">  音乐
  <input type="checkbox" name="hobby" id="hobby2">  登山
  <input type="checkbox" name="hobby" id="hobby3">  游泳
  <input type="checkbox" name="hobby" id="hobby4">  阅读
  <input type="checkbox" name="hobby" id="hobby5">  打球
  <input type="checkbox" name="hobby" id="hobby6">  跑步 
  <input type="button" value = "全选" id="button1">
  <input type="button" value = "全不选" id="button1">
  • document.getElementsByTagName("input"),结果为获取所有标签为input的元素,共8个。

  • document.getElementsByName("hobby"),结果为获取属性name="hobby"的元素,共6个。

  • document.getElementById("hobby6"),结果为获取属性id="hobby6"的元素,只有一个,"跑步"这个复选项。

三、节点属性

3.1、属性详解

在文档对象模型 (DOM) 中,每个节点都是一个对象。

属性 描述
nodeName 节点的名称:返回一个字符串,其内容是给定节点的名字
nodeType 节点的类型: 返回一个整数,这个数值代表给定节点的类型
nodeValue 节点的值: 返回给定节点的当前值

3.1.1、 nodeName 属性

节点的名称,是只读的。

说明

  • 元素节点的 nodeName 与标签名相同
  • 属性节点的 nodeName 是属性的名称
  • 文本节点的 nodeName 永远是 #text
  • 文档节点的 nodeName 永远是 #document

3.1.2、 nodeValue 属性

节点的值

说明

  • 元素节点的 nodeValueundefinednull
  • 文本节点的 nodeValue 是文本自身
  • 属性节点的 nodeValue 是属性的值

3.1.3、nodeType 属性

节点的类型,是只读的。

以下常用的几种结点类型:

元素类型 节点类型
元素 1
属性 2
文本 3
注释 8
文档 9

3.2、属性值获取:getAttribute() 方法

通过元素节点的属性名称获取属性的值。


语法

elementNode.getAttribute(name)

说明:

  • elementNode:使用 getElementById()getElementsByTagName()等方法,获取到的元素节点。
  • name:要想查询的元素节点的属性名字

举例: 获取 h1 标签的属性值:

<!DOCTYPE HTML>
<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html;charset=gb2312"/>
		<title>getAttribute()</title>
	</head>
	<body>
		<h1 id="alink" title="getAttribute()获取标签的属性值" onclick="hattr()">点击我,获取标签的属性值</h1>
	
		<script type="text/javascript">
		  function hattr(){
		     var anode = document.getElementById("alink");
			 var attr1 = anode.getAttribute("id");
			 var attr2 = anode.getAttribute("title");
			 document.write("h1标签的ID:" + attr1 + "<br>");
			 document.write("h1标签的title:" + attr2 );
		  }
		</script>
	</body>
</html>

运行结果:

h1标签的ID :alink
h1标签的title :getAttribute()获取标签的属值

3.3、 属性值设置: setAttribute() 方法

setAttribute() 方法增加一个指定名称和值的新属性,或者把一个现有的属性设定为指定的值。


语法

elementNode.setAttribute(name,value)

说明

  • name: 要设置的属性名。
  • value: 要设置的属性值。

注意

  • 把指定的属性设置为指定的值。如果不存在具有指定名称的属性,该方法将创建一个新属性。

  • 类似于getAttribute()方法,setAttribute()方法只能通过元素节点对象调用的函数。

四、 遍历节点树

属性 描述
childNodes 返回一个数组,这个数组由给定元素节点的子节点构成
firstChild 返回第一个子节点
lastChild 返回最后一个子节点
parentNode 返回一个给定节点的父节点
nextSibling 返回给定节点的下一个兄弟节点
previousSibling 返回给定节点的上一个兄弟节点

以层次图中 ul 为例,它的父级节点 body,它的子节点3li,它的兄弟结点h2P

4.1、childNodes

访问给定 元素节点 下 的所有子节点的列表。
返回的 值可以看作是一个数组,具有 length 属性。


语法

elementNode.childNodes

注意:如果选定的节点没有子节点,则该属性返回不包含节点的 NodeList


举例

<!DOCTYPE HTML>
<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
		<title>无标题文档</title>
	</head>
	<body>
		<ul>
			<li>JavaScript</li>
			<li>jQuery</li>
			<li>PHP</li>
		</ul>
		<script type="text/javascript">
		  var x = document.getElementByTagName("ul")[0].childNodes;
		  document.write("UL子节点个数:" + x.length + "<br />");
		  document.write("节点类型:" + x[0].nodeType);
		</script>
	</body>
</html>

运行结果: IE:

  UL子节点个数:3
  节点类型:1

其它浏览器:

   UL子节点个数:7
   节点类型:3

出现上述结果的原因如下:

  • IE全系列、firefox、chrome、opera、safari兼容问题
  • 节点之间的空白符,在firefox、chrome、opera、safari浏览器是文本节点,在 IE中会忽略掉。如下:
  <ul> 空白节点
     <li>javascript</li> 空白节点
	 <li>jQuery</li>  空白节点
	 <li>PHP</li>  空白节点
  </ul>

如果把代码改成这样:

<ul><li>javascript</li><li>jQuery</li><li>PHP</li></ul>

运行结果:(IE和其它浏览器结果是一样的)

  UL子节点个数:3
  节点类型:1

4.2、 firstChild and lastChild:访问子节点的第一和最后项

(1) firstChild 属性

返回 childNodes 数组的第一个子节点。
如果选定的节点没有子节点,则该属性返回 NULL。


语法:

node.firstChild

说明
      与 elementNode.childNodes[0] 是同样的效果。

(2)、 lastChild 属性

返回 childNodes 数组的最后一个子节点。
如果选定的节点没有子节点,则该属性返回 NULL。

语法:

node.lastChild

说明
      与 elementNode.childNodes[elementNode.childNodes.length-1] 是同样的效果。

注意: 上一节中,我们知道 Internet Explorer 会忽略节点之间生成的空白文本节点,而其它浏览器不会。我们可以通过检测节点类型,过滤子节点。 (以后章节讲解)

4.3、 访问父节点:parentNode

获取指定节点的父节点。

注意:
      浏览器兼容问题,chrome、firefox等浏览器标签之间的空白也算是一个文本节点。


语法:

elementNode.parentNode

注意:父节点只能有一个。


举例:
(1)、获取 P 节点的父节点,代码如下:

<div id="text">
  <p id="con"> parentNode 获取指点节点的父节点</p>
</div> 
<script type="text/javascript">
  var mynode= document.getElementById("con");
  document.write(mynode.parentNode.nodeName);
</script>

运行结果:

parentNode 获取指点节点的父节点
DIV

(2)、 访问祖节点:

elementNode.parentNode.parentNode

看看下面的代码:

<div id="text">  
  <p>
    parentNode      
    <span id="con"> 获取指点节点的父节点</span>
  </p>
</div> 
<script type="text/javascript">
  var mynode= document.getElementById("con");
  document.write(mynode.parentNode.parentNode.nodeName);
</script>

运行结果:

parentNode获取指点节点的父节点
DIV

4.4、 访问兄弟节点:nextSibling、previousSibling

(1)、nextSibling 属性

可返回某个节点之后紧跟的节点(处于同一树层级中)。


语法:

nodeObject.nextSibling

说明: 如果无此节点,则该属性返回 null。

(2)、 previousSibling 属性

可返回某个节点之前紧跟的节点(处于同一树层级中)。


语法:

nodeObject.previousSibling  

说明:如果无此节点,则该属性返回 null。


(3)、举例

注意:

  • 两个属性获取的是节点。
  • Internet Explorer 会忽略节点间生成的空白文本节点(例如,换行符号),而其它浏览器不会忽略。

如何获取正确的兄弟节点,解决方法:
      遍历兄弟节点时判断节点nodeType是否为1(元素节点),不是继续遍历直到获得的是 元素节点 为止。 如下代码:

<!DOCTYPE HTML>
<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
		<title>nextsibling</title>
	</head>
	<body>
		<ul id="u1">
			<li id="a">javascript</li>
			<li id="b">jquery</li>
			<li id="c">html</li>
		</ul>
		<ul id="u2">
			<li id="d">javascript</li>
			<li id="e">jquery</li>
			<li id="f">html</li>
		</ul>
		<script type="text/javascript">
		  function get_nextSibling(n){
		    var x=n.nextSibling;
			while(x.nextSibling != 1){
			  x = x.nextSibling;
			}
			
			retrun x;
		  }
		  var x = document.getElementByTagName("li")[0];
		  document.write(x.nodeName);
		  document.write("=");
		  document.write(x.innerHTML);
		  
		  var y = get_nextSibling(x);
		  document.write("nextSibling:" + y.nodeName);
		  document.write("=");
		  document.write(y.innerHTML); 
		</script>
	</body>
</html>

运行结果:

LI = javascript
nextsibling: LI = jquery

五、修改节点树

方法 描述
createElement(element) 创建一个新的元素节点
createTextNode() 创建一个包含给定文本的新文本节点
appendChild() 指定节点的最后一个子节点列表之后添加一个新的子节点
insertBefore() 将一个给定节点插入到一个给定元素节点的给定子节点前面
removeChild() 从一个给定元素中删除一个子节点
replaceChild() 把一个给定父元素里的一个子节点替换为另外一个节点

注意: 前两个是 document 方法。

5.1、 创建节点

(1)创建 元素 节点:createElement

createElement() 方法可创建元素节点。 此方法可返回一个 Element 对象。


语法:

document.createElement(tagName)

参数:

tagName:字符串值,这个字符串用来指明创建元素的类型。

注意:要 与 appendChild() 或 insertBefore() 方法联合使用,创建后将元素显示在页面中。


实例: 我们来创建一个按钮,代码如下:

<script type="text/javascript">
   var body = document.body; 
   var input = document.createElement("input");  
   input.type = "button";  
   input.value = "创建一个按钮";  
   body.appendChild(input);  
 </script>  

**效果:**在HTML文档中,创建一个按钮。

我们也可以使用 setAttribute(见第五章节) 来设置属性,代码如下:

<script type="text/javascript">  
   var body= document.body;             
   var btn = document.createElement("input");  
   btn.setAttribute("type", "text");  
   btn.setAttribute("name", "q");  
   btn.setAttribute("value", "使用setAttribute");  
   btn.setAttribute("onclick", "javascript:alert('This is a text!');");       
   body.appendChild(btn);  
</script>  

效果: 在HTML文档中,创建一个文本框,使用setAttribute设置属性值。 当点击这个文本框时,会弹出对话框“This is a text!”。

(2)创建文本节点:createTextNode

createTextNode() 方法创建新的文本节点,返回新创建的 Text 节点。


语法:

document.createTextNode(data)

参数: data : 字符串值,可规定此节点的文本。


实例: 我们来创建一个 <div> 元素并向其中添加一条消息,代码如下:

<!DOCTYPE HTML>
<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
		<title>无标题</title>
		<style type="text/css">
		  .message{
		     width:200px;
			 height:100px;
			 background-color:#CCC;
		  }
		</style>
	</head>
	<body>
		<script type="text/javascript">
		  var element = document.createElement("div");
		  element.className = "message";
		  
		  var textNode = document.createTextNode("Hello world!");
		  element.appendChild(textNode);
		  document.body.appendChild(element);
		</script>
	</body>
</html>

运行结果:
输入图片说明

5.2、 插入节点

(1) appendChild()

在指定节点的最后一个子节点列表之后添加一个新的子节点。


语法

appendChild(newnode)

参数:

  • newnode:指定追加的节点。

实例


	    <div id="test"><p id="x1">HTML</p><p>JavaScript</p></div>
	    <script type="text/javascript">
		    var otest = document.getElementById("test");
			var newnode = document.createElement("p");
			newnode.innerHEML = "This is a new p";
			// appendChild方法添加节点
			otest.appendChild(newnode);
		</script>

运行结果:

HTML
JavaScript
This is a new p

(2) insertBefore()

insertBefore() 方法可在已有的子节点前插入一个新的子节点。


语法

insertBefore(newnode,node);

参数:

  • newnode: 要插入的新节点。
  • node: 指定此节点前插入节点。

实例

<!DOCTYPE HTML>
<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
		<title>无标题</title>
	</head>
	<body>
	    <div id="div1"><p id="x1">JavaScript</p><p>HTML</p></div>
	    <script type="text/javascript">
		    var otest = document.getElementById("div1");
			var node = document.getElementById("x1");
			var newnode = document.createElement("p");
			newnode.innerHEML = "This is a new p";
			otest.insertBefore(newnode,node);
		</script>
	</body>
</html>

运行结果:

This is a new p
JavaScript
HTML

注意
otest.insertBefore(newnode,node);
也可以改为:
otest.insertBefore(newnode,otest.childNodes[0]);

5.3、 删除节点:removeChild()

removeChild() 方法从子节点列表中删除某个节点。
如删除成功,此方法可返回被删除的节点,如失败,则返回 NULL。


语法:

nodeObject.removeChild(node)

参数:

  • node :必需,指定需要删除的节点。

实例

<!DOCTYPE HTML>
<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
		<title>无标题</title>
	</head>
	<body>
	    <div id="div1"><h1>HTML</h1><h2>javascript</h2></div>
	    <script type="text/javascript">
		    var otest = document.getElementById("div1");
			var x = otest.removeChild(otest.childNodes[1]);
			document.write("删除节点的内容:" + x.innerHTML);
		</script>
	</body>
</html>

运行结果:

HTML
删除节点的内容: javascript

注意:

  • 把删除的子节点赋值给 x,这个子节点不在 DOM 树中,但是还存在内存中,可通过 x 操作。

  • 如果要完全删除对象,给 x 赋 null 值,代码如下:


   var otest = document.getElementById("div1");
   var x = otest.removeChild(otest.childNodes[1]);
   x=null;

5.4、 替换元素节点:replaceChild()

replaceChild 实现子节点(对象)的替换。返回被替换对象的引用。


语法:

node.replaceChild (newnode,oldnew )

参数:

  • newnode : 必需,用于替换 oldnew 的对象。
  • oldnew : 必需,被 newnode 替换的对象。

举例:

<!DOCTYPE HTML>
<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
		<title>无标题</title>
	</head>
	<body>
	<script type="text/javascript">
		  function replaceMessage(){
		    var newnode=document.createElement("p");
			var newnodeText = document.createTextNode("JavaScript");
			
			newnode.appendChild(newnodeText);
			
			var oldNode = document.getElementById("oldnode");
			oldnode.parentNode.replaceChild(newnode,oldnode);
		  }
		</script>
		<h1 id="oldnode">Java<h1>
		<a href="javascript:replaceMessage()">"Java" 替换 "JavaScript"</a>
		
	</body>
</html>

**效果 **: 将 文档中的 Java 改为 JavaScript

注意:

  • 当 oldnode 被替换时,所有与之相关的属性内容都将被移除。
  • newnode 必须先被建立。
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!