第9章-DOM文档对象模型

本文深入讲解了DOM(文档对象模型)的基础概念与操作技巧,包括如何通过JavaScript访问、修改及创建HTML元素,探讨了DOMDocument、DOMElement、DOMEvent等核心对象的使用,以及事件绑定与处理的多种方式。

一、认识DOM对象:

文档对象模型(Document Object Model,DOM)是W3C组织推荐的处理可扩展标志语言的标准编程接口。HTML DOM是W3C标准,定义了用于HTML的一系列标准的对象,以及访问和处理HTML文档的标准方法。HTML DOM把HTML文档呈现为带有元素、属性和文本的树结构(节点树)。

通过DOM,可以访问所有的 HTML元素,连同它们包含的文本和属性。可以对其中的内容进行修改和删除,同时也可以创建新的元素。HTML DOM 独立于平台和编程语言。它可被任何编程语言(如 Java、JavaScript 和 VBScript)使用。

通过可编程的对象模型,JavaScript 获得了足够的能力创建动态的 HTML,主要包括:

1)JavaScript 能够改变页面中的所有 HTML 元素。

2)JavaScript 能够改变页面中的所有 HTML 属性。

3)JavaScript 能够改变页面中的所有 CSS 样式。

4)JavaScript 能够对页面中的所有事件做出反应。

二、HTML DOM Document 对象:

HTML DOM Document 对象表示每个载入浏览器的 HTML 文档。Document 对象使我们可以从脚本中对 HTML 页面中的所有元素进行访问。Document 对象是 window 对象的一部分,可通过 window.document 属性对其进行访问。

Document 对象是 JavaScript 实现网页各种功能中最常用的基本对象之一,它代表浏览器窗口中的文档,可以用来处理文档中包含的 html 元素,如表单、图片、超链接等。

1.获取页面元素

通常通过 JavaScript 操作 HTML元素,需要使用 getElementById()、getElementsByName()或 getElementsByTagName() 3 个方法之一获取指定的 HTML 元素对象或对象集合。

1)getElementById()

通过 HTML 标签的 id 属性获得一个 HTML 元素对象,返回具有该 id属性的 HTML 元素对象。如:

var username = document.getElementById("username").value;

2)getElementsByName()

通过 HTML 标签的 name 属性获得一些元素对象,返回的是具有相同 name 属性的 HTML 元素的集合。如,要获取表单中第一个 name 属性值为 username 的文本框的输入内容,可以使用如下语句:

var un=document.getElementsByName("username");
var username = un[0].value;

3)getElementsByTagName()

通过 HTML 标签名获得指定标签名的 HTML 元素对象集合。如,要获取表单中第一个标签为 input 的输入控件的输入内容,可以使用如下语句:

var un = document.getElementsByTagName("input");
var username = un[0].value;

2.修改页面元素

获取页面元素后,可以改变页面元素的样式、内容和属性等。改变的方法如下:

1)改变 HTML 元素的内容

document.getElementById(id).innerHTML=new HTML

document.getElementById(id).text=new Text

document.getElementById("title").innerHTML="<h1>这是标题</h1>"

2)改变 HTML 元素的属性

document.getElementById(id).attribute=new value

document.getElementById("image").src="img/flower.jpg"

3)改变 HTML 元素的样式

document.getElementById(id).style=new style

document.getElementById("book").style.display="none"

3.添加/删除页面元素

1)创建新的 HTML 元素

下面这段代码用于创建新的<p>元素,然后创建并追加一个文本节点:

var para=document.createElement("p");
var node=document.createTextNode("这是新段落");
para.appendChild(node);

也可以先找到一个已有的元素再添加新元素:

var element=document.getElementById("div1");
element.appendChild(para);

 2)删除已有的 HTML 元素

如需删除 HTML 元素,必须首先获得该元素的父元素。

假设 HTML 文档含有一个 div 元素,该 div 有两个子节点:

<div id="div1">
    <p id="p1">这是一个段落。</p>
    <p id="p2">这是另一个段落。</p>
</div>

删除子节点的操作如下: 

/*找到 id="div1"的元素*/
var parent=document.getElementById("div1");
/*找到 id="p1"的<p>元素*/
var child=document.getElementById("p1");
/*从父元素中删除子元素*/
parent.removeChild(child);

 4.form 对象

当 JavaScript 读到 HTML标签中对应的 form 表单输入控件标签时,会自动建立一个该类型的 form 子对象,并将该对象存放到 form 对象的 elements 数组中。document 的对象集合中,forms 代表 form 对象集合。

对表单的子对象的访问可以有以下 3 种格式:

1)利用表单对象的 elements 属性访问:

document.forms[n].elements[n].子对象属性名

document.forms[n].elements[n].子对象方法名

2)利用表单名和子对象名访问:

document.forms[n].elements[n].子对象属性名

document.forms[n].elements[n].子对象方法名

3)混合访问方式:

document.forms[n].子对象名.子对象属性名

document.forms[n].子对象名.子对象方法名

三、HTML DOM Event 对象:

HTML DOM Event 对象表示事件的状态,如事件在其中发生的元素、键盘按键的状态、鼠标的位置、鼠标按钮的状态等。

四、HTML DOM Element 对象:

HTML DOM Element 对象表示任意的 HTML元素。元素对象可以拥有类型为元素节点、文本节点、注释节点的子节点。NodeList 对象表示节点列表,如 HTML 元素的子节点集合。元素也可以拥有属性,属性是属性节点。

element 对象的属性和方法可用于所有 HTML 元素。

利用 element 对象的属性,可以帮助我们遍历文档元素和节点。

如,使用 parentNode 属性,获取父元素:

<form id="form">
    <div id="divA">
        <div id="divB">
            <input type="button" value="删除" onClick="deleteMe(this.parentNode.parentNode);">
        </div>
    </div>
</form>

所谓 parentNode,是其上一层节点,里面的 this.parentNode 是 divB,而 this.parentNode.parentNode 是 divA。

如,使用 firstChild 和 lastChild 获取子元素:

<div id="div1">
    <div id="div2"></div>
</div>
<script>
    var oDiv=document.getElementById("div1");
    var oDiv2=document.getElementById("div2");
    alert(oDiv.firstChild.nodeName);
    alert(oDiv.lastChild.nodeName);
</script>

输出的第一个和最后一个节点,结果是#text,也就是文本节点,而不是设想中的 DIV 节点。这是由于节点前后有空格造成的。

由于编码时格式的需要,HTML 代码会有很多空格或空行。在 HTML文件中,空格也算子节点,节点名称是#text,节点类型是文本。

当去掉 div 元素的空格的换行后,代码如下:

<div id="div1"><div id="div2"></div></div>
<script>
    var oDiv=document.getElementById("div1");
    var oDiv2=document.getElementById("div2");
    alert(oDiv.firstChild.nodeName);// 输出:DIV
    alert(oDiv.lastChild.nodeName);// 输出:DIV
</script>

所以,尽量避免使用 firstChild、lastChild、childNodes[0]或类似的节点选取,可以使用 firstElementChild、lastElementChild 代替。

五、HTML DOM attribute 对象:

在 HTML DOM 中,attribute 对象表示 HTML 属性,NamedNodeMap 对象表示元素属性节点的无序集合,其中的节点可通过名称或索引访问。

六、DOM与事件:

1.事件绑定的方式

JavaScript 给 DOM 绑定事件处理函数,有以下 5 种方式:

1)HTML 的 DOM 元素支持 onclick、onchange 等以 on 开头的属性,可以直接在这些属性值中编写 JavaScript 代码。

如,当单击 div 的时候,下面代码弹出 div 的 id:

<div id="outsetA" onClick="var id=this.id;alert(id);return false;"></div>

此处,onClick 属性中的 this 代表的是当前被单击的 DOM 对象,所以我们可以通过 this.id 获取 DOM 元素的 id 属性值。

2)当代码比较多时,可以在 onClick 等属性中指定函数名。

<script>
    function buttonHandler(thidDom) {
        alert(this.id);//undefined
        alert(thisDom.id);//outsetA
        return false;
    }
</script>
<div id="outsetA" onClick="return buttonHandler(this);"></div>

事件处理函数中的 this 代表的是 window 对象,而 onClick 属性值中的 this 代表 DOM 对象并作为参数传递。

3)在 JavaScript 代码中通过 DOM 元素的 onClick 等属性绑定。

var dom=document.getElementById("outsetA");
dom.onClick=function(){alert("1="+this.id);};
dom.onClick=function(){alert("2="+this.id);};

这种做法中的 this 代表当前的 DOM 对象。这种做法只能绑定一个事件处理函数,后面的会覆盖前面的。

4)在 IE 下使用 attachEvent/detachEvent 函数进行事件绑定和取消。IE6~IE11 才支持,并且FireFox 和 Chrome 都不支持,并且也不是 W3C 标准的做法,所以不推荐使用。

5)使用 W3C 标准的 addEventListener 和 removeEventListener。

这两个函数是 W3C 标准规定的,FireFox/Chrome/IE9 都支持这两个标准的 API。

addEventListener(type, listener, useCapture);

type:事件类型,不含“on”,如“click”、“mouseover”、“keydown”。

listener:事件处理函数。

useCapture:代表事件冒泡类型是事件冒泡,还是事件捕获,默认为 false(事件冒泡)。

➀事件处理函数中 this 代表的是 DOM对象,不是 Window。

var dom=document.getElementById("outsetA");
dom.addEventListener('click',a,false);
function a() {
    alert(this.id);//输出:outsetA
}

➁同一个事件处理函数可以绑定两次,一次用于事件捕获,一次用于事件冒泡。

var dom=document.getElementById("outsetA");
dom.addEventListener('click',a,false);
dom.addEventListener('click',a,true);
function a() {
    alert(this.id);//输出:outsetA
}

当单击 outsetA 时,函数 a 会调用 2 次。如果绑定的是同一个事件处理函数,并且都是事件冒泡类型或者事件捕获类型,那么只能绑定一次。 

➂不同的事件处理函数可以重复绑定。

2.事件处理函数的执行顺序

如果给同一个事件绑定多个处理函数,先绑定的先执行,如:

<script>
    window.onload=function(){
        var outA=document.getElementById("outA");
        outA.addEventListener('click',function(){alert(1);},false);
        outA.addEventListener('click',function(){alert(2);},true);
        outA.addEventListener('click',function(){alert(3);},true);
        outA.addEventListener('click',function(){alert(4);},true);
    };
</script>
<body>
    <div id="outA" style="width:400px;height:400px;background:#CDC9C9;position:relative;">
    </div>
</body>

当单击 outA 时,会依次打印出 1、2、3、4。要注意:给 outA 绑定了多个 onClick 事件处理函数,也就是直接单击 outA 触发事件,所以不涉及事件冒泡和事件捕获的问题,即 addEventListener 的第三个参数在这种场景下没有什么用处。如果是通过事件冒泡或事件捕获触发 outA 的 click 事件,那么函数的执行顺序会有变化。

3.事件冒泡和事件捕获

HTML 中的元素是可惜嵌套的,形成类似于树的层次关系,如:

<div id="outA" style="width:400px;height:400px;background:#CDC9C9;position:relative;">
    <div id="outB" style="height:200;background:#0000ff;top:100px;position:relative;">
        <div id="outC" style="height:100px;background:#FFB90F;top:50px;position:relative;">
        </div>
    </div>
</div>

如果单击了最内侧的 outC,那么外侧的 outB 和 outA 很明显也算是被单击了。

如果浏览器采用的是事件冒泡,那么触发的顺序是 C->B->A,由内而外,像气泡一样,从水底浮向水面;

如果浏览器采用的是事件捕获,那么触发的顺序是A->B->C,从上到下,像石头一样,从水面落入水底。

<script>
    window.onload=function(){
        var outA=document.getElementById("outA");
        var outB=document.getElementById("outB");
        var outC=document.getElementById("outC");
        //使用事件冒泡
        outA.addEventListener('click',function(){alert(1);},false);
        outB.addEventListener('click',function(){alert(2);},false);
        outC.addEventListener('click',function(){alert(3);},false);
    };
</script>
<body>
<div id="outA" style="width:400px;height:400px;background:#CDC9C9;position:relative;">
    <div id="outB" style="height:200;background:#0000ff;top:100px;position:relative;">
        <div id="outC" style="height:100px;background:#FFB90F;top:50px;position:relative;">
        </div>
    </div>
</div>
</body>

以上代码使用的是事件冒泡(默认值),当单击outC时,打印顺序是3->2->1。如果将false改为true使用事件捕获,则打印顺序是1->2->3。

项目实战:诗词鉴赏

<html>
<head>
  <style>
	body{
	background:url(./卷轴.jpg) no-repeat;
	background-position:50% 0;
	}
	#box1{width:750px;height:350px;padding:10px;margin:140px auto;}
	#box2{font-family:隶书; font-size:1.5em;font-weight:bold;
	width:300px;height:250px;
	float:left;margin:40px 10px;padding:10px;
	text-align:center;letter-spacing:2px;}
	#box3{width:350px;height:250px;padding:100px 10px;float:right}
	img{position:relative;right:-150px;border-radius:15px}
  </style>
<script language="JavaScript">
  function changecolor(){  
	var color= document.getElementsByName("colorpanel");
	document.getElementById("box2").style.color=color[0].value; 
  }

  function changecontent(){
	var t1=document.getElementsByName("txt1");
	var div1=document.getElementsByTagName("div");
	div1[1].innerHTML="<p>"+t1[0].value+"<p>";
  }
  
  function hide(){
	document.getElementById("box2").style.display="none";
  }
  
  function show(){
	document.getElementById("box2").style.display="block";
  }
  
  function add(){
	var t2=document.getElementsByName("txt2");
	var div2=document.getElementsByTagName("div");
	div2[1].innerHTML+="<p>"+t2[0].value+"</p>";
  }

  function clr(event){ 
	event.srcElement.value="";  
  }
</script>
</head>
 <body>
	<div id="box1">
		<div id="box2"><p>离离原上草</p></div>
	<div id="box3">  
	<!--改内容-->
	<input TYPE="text" name="txt1"  onfocus="clr(event)">
	<button onclick="changecontent()">换一首诗</button><br><br>
	<!--添加内容-->
	下一句诗
	<input TYPE="text" name="txt2" onfocus="clr(event)">
	<button onclick="add()">添加</button><br><br>
	<!--背景色-->
	<input TYPE="color" name="colorpanel">
	<button onclick="changecolor()">改颜色</button> <BR><BR>
	<!--隐藏、显示-->
	<button onclick="hide()">隐藏</button> 
	<button onclick="show()">显示</button><br><br>
	</div></div>
 </body>
</html>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

itzyjr

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值