论坛首页 Web前端技术论坛

理解DOM_通过DOM方法找到节点

浏览 1657 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2011-12-30   最后修改:2011-12-30

 


截屏(2011-12-26 01_29_22).jpg

 

    还是从这幅图开始,DOM通过树这个模型很好地映射了HTML文档,使得javascript对文档的访问和修改成为可能。

    我们看到的web页面是表现形式,它传达信息,提供用户交互的界面和元素。浏览器会自动维护一个与页面相关的DOM对象,对象在页面载入时应该与页面的结构形成一一映射的关系,当然DOM对象是动态的,动态意味着可变,同时许多变化会在页面上实时地表现出来,可以类比MVC模式:DOM似乎可以看做控制器Controller,而我们看到的页面是一个视图View。改变控制器行为,会带来视图的响应变化。

    可以打开Firebug这个插件,去查看浏览器动态维护的文档结构。

 

截屏(2011-12-28 00_47_36).jpg 

 

    改变的前提是精确定位,过程大概如此:通过一些方法找到节点,这个节点通过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);

   截屏(2011-12-28 01_34_35).jpg

 

任务2:返回的是一个对象数组吗?

思路:遍历返回数组,试用typeof操作符确定数组中每一个元素的类型,然后显示

 

var pArray = document.getElementsByTagName("p");
for(var i = 0; i < pArray.length; i++) {
   alert("第 " + ( i +1 ) + " 个元素是一个 " + typeof pArray[i]); // 下标从0计数
}

   截屏(2011-12-28 01_42_22).jpg

 

任务3:显示第二个<p>元素内的文字(innerText属性会在后文中详细介绍)

思路:定位第二个元素,下标为1

 

var pArray = document.getElementsByTagName("p");
var text = pArray[1].innerText;
alert(text);

   截屏(2011-12-28 01_46_47).jpg

 

    通过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。

    截屏(2011-12-30 00_45_08).jpg

    我们通过钩子“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。框架在易用的同时有一定的依赖性,特别对对基础知识掌握不太好的同学,弊大于利。

 

 

 

论坛首页 Web前端技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics