?
?
????还是从这幅图开始,DOM通过树这个模型很好地映射了HTML文档,使得javascript对文档的访问和修改成为可能。
??? 我们看到的web页面是表现形式,它传达信息,提供用户交互的界面和元素。浏览器会自动维护一个与页面相关的DOM对象,对象在页面载入时应该与页面的结构形成一一映射的关系,当然DOM对象是动态的,动态意味着可变,同时许多变化会在页面上实时地表现出来,可以类比MVC模式:DOM似乎可以看做控制器Controller,而我们看到的页面是一个视图View。改变控制器行为,会带来视图的响应变化。
??? 可以打开Firebug这个插件,去查看浏览器动态维护的文档结构。
?
?
??? 改变的前提是精确定位,过程大概如此:通过一些方法找到节点,这个节点通过DOM抽象成为了javascript对象,基于这个对象通过一些方法进行操作,使得DOM发生改变,同时反映在页面上。
??? 这个描述有一些含糊,从第一句开始消除模糊:(谁)通过(哪些)方法找到(什么)节点。
??? 回到上面的树形图,来定义谁,首先它应该拥有一些子节点,我们的需求是寻找它的某个或者(某些)子节点。如果它囊括了其他所有节点,那么它应该是html这个根节点。如果它只含有一部分子节点,那么它可能是ul节点。
????html是树根,也是直尺上的“0”刻度,那么它就一定是那个“谁”吗?在HTML中<html>是当之无愧的老大标签,而在DOM,是通过document对象映射HTML文档的,所以document对象是那个“谁”,当然其他元素也会充当那个“谁”,后面会提到。
??? 理清楚调用方法的一个主体,就可以开始“哪些”方法了。最显而易见的方法是直呼节点(标签)的名称,然后等待回复。
????document对象,提供了了一个getElementsByTagName的方法:方法接收一个字符串参数――节点的名称,然后返回一个对应的对象数组。
????数组是ECMAScript的内建对象,充当容器使用,通过整数索引可以取出对应位置的的元素。length属性记录了数组的长度,可以理解为容器的容积,这个属性使得循环、遍历等操作成为可能。
??? 为什么返回数组呢?因为一个页面中可能会含有多个相同的标签,多个――复数――Elements。
Example:
HTML
?
?
<html> <head> <title>This is an example</title> </head> <body> <p>Hello</p> <p>HuJin</p> <p>CaoLixiang</p> </body> </html>?
?
任务1:上面这个页面中有过少个<p></p>元素?
思路:document(文档的表示对象)调用getElementsByTagName方法,传入"p"――p便签的名字,然后显示返回的数组的长度。
?
?
var pArray = document.getElementsByTagName("p"); alert(pArray.length);?
? ?
?
任务2:返回的是一个对象数组吗?
思路:遍历返回数组,试用typeof操作符确定数组中每一个元素的类型,然后显示
?
?
var pArray = document.getElementsByTagName("p"); for(var i = 0; i < pArray.length; i++) { alert("第 " + ( i +1 ) + " 个元素是一个 " + typeof pArray[i]); // 下标从0计数 }??
? ?
?
任务3:显示第二个<p>元素内的文字(innerText属性会在后文中详细介绍)
思路:定位第二个元素,下标为1
?
?
var pArray = document.getElementsByTagName("p"); var text = pArray[1].innerText; alert(text);??
? ?
?
??? 通过getElementsByTagName方法,你可以找到任何一个元素,虽然它返回的是一个元素数组,但是仍然可以通过下标来精确定位。我需要找到<p>HuJin</p>这个元素,我记住它是第二个元素,找到它是小case:
var hujin = document.getElementsByTagName("p")[1];
??? 然后我对hujin这个对象巴拉拉一堆操作,改变下字体,背景颜色,为了突出以下,加上边框。到目前为止一切顺利,但是如果有一天页面结构发生了变化呢?
新的页面:
...
?
<p>Hello</p> <p>CaoLixiang</p> <p>HuJin</p>
?...
??? 这时,结果就在预期之外了,<p>CaoLixiang</p>就被巴拉拉了。
??? 如何使得标签与众不同呢?id这个属性一定不陌生,它是省份证,具有唯一性。id是很多标签内属性(囊括在<>之内)中的一个,通过添加id属性可以使得标签与众不同:
<p id="lovely">HuJin</p>
??? 这样<p>HuJin</p>这个标签就与其他p标签区别开来了。DOM对id属性具有良好的支持,getElementById是“哪些”方法中的一个,它接收一个字符串参数――id的值,返回一个对象――单数――Element。
??? 这样就可以随便对<p id="lovely">HuJin</p>巴拉拉了,因为我们总能找到它,上面那段代码可以适当加以修改:
?
?
var hujin = document.getElementById("lovely"); var text = hujin.innerText; alert(text);?
??? 结果总是在预期之内。
??? 一些人把id属性称为钩子,无论页面元素相对结构如何变化,始终可以精确定位。
? ??其实节点也能充当“谁”,下面这幅图中是一个html页面的一部分,我们只取出中间一部分,我们并不知道前面还有多少个<div>标签,以及我们需要的<p>标签是所有<p>中的第几个,但是我们知道这个<p>的相对位置,它从属于从中部分的<div>,并且相对位置是2。
???
??? 我们通过钩子“id”,先找到div元素。?
var divToBeFound = document.getElementById("target");? ?
??? 这时“谁”发生了变化,变为了div节点。这类节点有一个特性:高、富。高是因为所处的位置相对较高,富是因为它包含了其他元素节点(其他类型的节点在下一篇中展开)。
var found = divToBeFound.getElementsByTagName("p")[1];?
??? 就找到了我们的目标。这两个语句分开写,是希望更能清楚的说明调用方法的谁发生了变化。当然,你理解了其中的原理,便可以这样调用。?
var found = document.getElementById("target").getElementsByTagName("p")[1];
?
? ? 至此“谁”和“哪些”就明晰多了了。
?
?
写在最后的
??? 选择元素是一切操作的基础,dom提供了一系列方法用于选择元素。getElementById和getElementsByTagName联合起来作用很大,但是选择语句有时会很长。但是这些是应该去掌握和理解的。
??? 用过jQuery的同学,会发现选择变得容易许多,这个也是“query”的初衷,一个良好的库是能提供开发效率的。
??? 那么一开始就使用jQuery好吗?我觉得不是很好,就是很多人建议学习Java先从命令行、写字板开始一样,然后逐渐过渡到Eclipse;学习Java Web先从Servlet、Jsp开始,然后逐渐过渡到SSH。框架在易用的同时有一定的依赖性,特别对对基础知识掌握不太好的同学,弊大于利。
?
?
?
?