【AJAX进阶】--AJAX与DOM网页程序构建高手

       上篇文章对AJAX的运行机制进行了解读,它是一种异步的JavaScript在执行请求时程序仍能够操作页面上的其他元素,相对于传统的网页(要等待上一次操作完成后才能进行下面的操作)增加了用户的体验度。另外AJAX的在如今常应用到构建网页应用程序中,如我们常见的网页Ps,GoogleMap等。


一、文档对象模型--DOM


       上篇文章虽然解读了网页的运行过程,但你可能会疑问,当 HTML 或为页面定义的 CSS 发送给 Web 浏览器后它是如何被浏览器认识并执行的?别着急下面的内容将会解答这个问题。


       先来解答上面的问题,当 HTML 或为页面定义的 CSS 发送给 Web 浏览器时,网页被从文本转化成对象模型,对象模型中封装了要请求的网页的所有元素。无论代码简单或复杂,集中到一个文件还是分散到多个文件,都是如此。然后浏览器直接使 用 对 象 模 型 而 不 是 您 提 供 的 文 本 文 件 。 浏 览 器 使 用 的 模 型 称 为 文 档 对 象 模 型(DocumentObjectModel,DOM)。它连接表示文档中元素、属性和文本的对象。HTML 和 CSS 中所有的样式、值、甚至大部分空格都合并到该对象模型中。给定网页的具体模型称为该页面的 DOM树。
【AJAX进阶】--AJAX与DOM网页程序构建高手

  1、了解 DOM 树


        已经知道了 HTML 和 CSS被转化为DOM 仅仅是控制 Web 页面的第一步,接下来还需要了解如何处理 Web 页面的 DOM 树。比方说,如果向 DOM 树中增加一个元素,这个元素就会立即出现在用户的 Web 浏览器中——不需要重新加载页面。从 DOM 树中删除一些文本,那些文本就会从用户屏幕上消失。可以通过 DOM 修改用户界面或者与用户界面交互,这样就提供了很强的编程能力和灵活性。一旦学会了如何处理 DOM 树,您就向实现丰富的、交互式动态网站迈出了一大步。

   1.1 节点


       节点是 DOM 中最基本的对象类型。实际上,基本上 DOM 定义的其他所有对象都是节点对象的扩展。在 DOM 树中,基本上一切都是节点。每个元素在最底层上都是 DOM 树中的节点。每个属性都是节点。每段文本都是节点。甚至注释、特殊字符(如版权符号?)、DOCTYPE 声明(如果 HTML或者 XHTML 中有的话)全都是节点。因此在讨论这些具体的类型之前必须清楚地把握什么是节点。如下图的节点排列:

【AJAX进阶】--AJAX与DOM网页程序构建高手

      节点究竟是?
          用最简单的话说,DOM 树中的任何事物都是节点。之所以用“事物”这个模糊的字眼,是因为只能明确到这个程度 。 比如HTML中的元素( 如 img )和HTML中的文本片段 ( 如“这是一个if循环”)没有多少明显的相似之处。但这是因为您考虑的可能是每种类型的功能,关注的是它们的不同点。

         但是如果从另一个角度观察,DOM 树中的每个元素和每段文本都有一个父亲,这个父节点可能是另一个元素(比如嵌套在 p 元素中的 img)的孩子,或者 DOM 树中的顶层元素(这是每个文档中都出现一次的特殊情况,即使用 html 元素的地方)。另外,元素和文本都有一个类型。显然 ,元素的类型就是元素,文本的类型就是文本。每个节点还有某种定义明确的结构:下面还有节点(如子元素)吗?有兄弟节点(与元素或文本“相邻的”节点)吗?每个节点属于哪个文档?答案是当然有,即使是页面的顶层元素仍然拥有它的父节点。


      1.1.1 节点的属性

        使用 DOM 节点时需要一些属性和方法,因此我们首先来讨论节点的属性和方法。不常用的属性上述大部分属性的意义都很明确,除了 nodeName 和 nodeValue 属性以外。我们不是简单地解释这两个属性,而是提出两个奇怪的问题:文本节点的 nodeName 应该是什么?类似地,元素的nodeValue 应该是什么?

       如果这些问题难住了您,那么您就已经了解了这些属性固有的含糊性。 nodeName 和 nodeValue实际上并非适用于所有节点类型(节点的其他少数几个属性也是如此)。这就说明了一个重要概念:任何这些属性都可能返回空值(有时候在 JavaScript 中称为“未定义”)。比方说,文本节点的 nodeName 属性是空值(或者在一些浏览器中称为“未定义”),因为文本节点没有名称。如您所料,nodeValue 返回节点的文本。类似地,元素有 nodeName,即元素名,但元素的 nodeValue 属性值总是空。属性同时具有nodeName 和 nodeValue。下一节我还将讨论这些单独的类型,但是因为这些属性是每个节点的一部分,因此在这里有必要提一提。

       学习完上面的内容后现在是时候来在代码中实践使用属性了,现在看看清单 1,它用到了一些节点属性。


       清单 1:使用 DOM 中的节点属性来获取Dom树中的元素信息

<script type=‘text/javascript‘>
	//**************************************************************************
	//该代码示例采用节点的属性来获取Dom树中的<head>、<body>等元素,并显示这些元素的信息
	//**************************************************************************

	//下面的语句是用来获取网页的Dom树
	var myDocument=document;
	//下面的语句获取网页中的<html>节点
	var htmlElement=myDocument.documentElement;

	//弹出提示框显示该网页的<html>的节点名称
	alert("The root element of the page is"+htmlElement.nodeName);

	//下面的语句用来查找<head>节点
	var headElement=htmlElement.getElementsByTagName("head")[0];

	if(headElement!=null){
		alert("We found the head element,named"+headElement.nodeName );
		//获取页面的标题<title>元素
		var titleElement=headElement.getElementsByTagName("title")[0];

		if(titleElement!=null){

			//获取<title>中的第一个子元素
			var titleText=titleElement.firstChild;

			//使用nodeValue属性获取节点的节点文本
			alert("The page title is‘"+titleText.nodeValue +"‘");
		}

		//在<head>标签后查找标签<body>
		var bodyElement=headElement.nextSibling;
		while(bodyElement.nodeName .toLowerCase()!="body"){
			bodyElement=bodyElement.nextSibling;
		}
		
		alert("We found the <body> node");
		
	}

</script>

     1.1.2 节点方法

      接下来看看所有节点都具有的方法(与节点属性一样,只介绍了多数 HTMLDOM操作的方法,一些不常用的方法还清查看DOM API文档了):

       insertBefore(newChild,referenceNode):将 newChild 节点插入到 referenceNode 之前。记住,应该对 newChild 的目标父节点调用该方法。
        replaceChild(newChild,oldChild):用 newChild 节点替换 oldChild 节点。
        removeChild(oldChild):从运行该方法的节点中删除 oldChild 节点。
        appendChild(newChild):将 newChild 添加到运行该函数的节点之中。newChild 被添加到目标节点孩子列表中的末端。
        hasChildNodes():在调用该方法的节点有孩子时则返回 true,否则返回 false。
        hasAttributes():在调用该方法的节点有属性时则返回 true,否则返回 false。


       Note:大部分情况下所有这些方法处理的都是节点的孩子。这是它们的主要用途。如果仅仅想获取文本节点值或者元素名,则不需要调用这些方法,使用节点属性就可以了。


     清单 2:使用 DOM 中的节点方法,删除所有body标签中所有的*img标签

//删除body标签中所有的*img标签
if(bodyElement.hasChildNodes()){
	for(i=0;i<bodyElement.childNodes.length;i++){
		var currentNode=bodyElement.childNodes[i];
		if(currentNode.nodeName.toLowerCase()=="img"){
			bodyElement.removeChild(currentNode);
		}
	}
}

   清单3 :上面示例中的完整的html+Javascript+Dom源码

<!doctype html>
<html lang="en">
 <head>
  <meta charset="UTF-8">
  <meta name="Generator" content="EditPlus®">
  <meta name="Author" content="">
  <meta name="Keywords" content="">
  <meta name="Description" content="">
  <title>Document</title>
  <script type=‘text/javascript‘>
	//**************************************************************************
	//该代码示例采用节点的属性来获取Dom树中的<head>、<body>等元素,并显示这些元素的信息
	//**************************************************************************
	function test(){
		//下面的语句是用来获取网页的Dom树
		var myDocument=document;
		//下面的语句获取网页中的<html>节点
		var htmlElement=myDocument.documentElement;

		//弹出提示框显示该网页的<html>的节点名称
		alert("The root element of the page is"+htmlElement.nodeName);

		//下面的语句用来查找<head>节点
		var headElement=htmlElement.getElementsByTagName("head")[0];

		if(headElement!=null){
			alert("We found the head element,named"+headElement.nodeName );
			//获取页面的标题<title>元素
			var titleElement=headElement.getElementsByTagName("title")[0];

			if(titleElement!=null){

				//获取<title>中的第一个子元素
				var titleText=titleElement.firstChild;

				//使用nodeValue属性获取节点的节点文本
				alert("The page title is‘"+titleText.nodeValue +"‘");
			}

			//在<head>标签后查找标签<body>
			var bodyElement=headElement.nextSibling;
			while(bodyElement.nodeName .toLowerCase()!="body"){
				bodyElement=bodyElement.nextSibling;
			}
			
			alert("We found the <body> node");
		}
		
		//使用节点方法,删除body节点下的所有顶层的img标签
		if(bodyElement.hasChildNodes()){
			for(i=0;i<bodyElement.childNodes.length;i++){
				var currentNode=bodyElement.childNodes[i];
				if(currentNode.nodeName.toLowerCase()=="img"){
					bodyElement.removeChild(currentNode);
				}
			}
		}
	}
	</script>
</head>
<body style="text-align:center;background-color:#CCCCCC">
	<p style="color:#CC0066">JavaScript and DOM are a perfect match.You can read more in <i>HeadRushAjax</i>.</p>
	<img src="http://www.headfirstlabs.com/Images/hraj_cover-150.jpg"/>
	<br/>
	<br/>
	<input type="button" value="Testme!" onClick="test();"/>
</body>
</html>

     示例运行效果:

【AJAX进阶】--AJAX与DOM网页程序构建高手
     单击Testme!按钮后运行结果为:

【AJAX进阶】--AJAX与DOM网页程序构建高手


结语


         经过上面的讨论相信已经对DOM不陌生,做到了不陌生这已经向熟练掌握DOM迈进了一大步,接下来多做一些Demo在Demo中运行DOM的方法和属性,想要熟练和灵活的使用AJAX和DOM就很简单了。最后再来回顾下文章的内容,文章从AJAX入手着重讨论了DOM的一些特性,其中包括基本的属性和方法,其实放到HTML或者XML中DOM其实是由一个个节点组合而成的,这些节点组成了DOM树,它们之间是能够相互转换的,另外使用DOM能够很容易的修改静态页面。


【AJAX进阶】--AJAX与DOM网页程序构建高手,布布扣,bubuko.com

【AJAX进阶】--AJAX与DOM网页程序构建高手

上一篇:使Visual Assist X V10.8.2029.0工具支持HTML、Javascript等语言


下一篇:CSS 中浮动的使用