JavaScript 第三课 DOM

主要内容:

  • 节点
  • 5个常用的DOM方法:

    getElementById、getElementByTagname、getElementByClassName、getAttribute和setAttribute


详细内容:

1、文档:DOM中的“D”

    如果没有document(文档),DOM也就无从谈起。当创建了一个网页并把它加载到Web浏览器中时,DOM就在幕后悄然而生。它把你编写的网页文档转换为一个文档对象。

2、对象:DOM中的“O”

对象是一种自足的数据集合。与特定某个对象相关联的变量成为这个对象的属性;只能通过某个特定对象去调用的函数称为这个对象的方法。

JavaScript语言中的对象可以分为三种类型。

用户定义对象:由程序员自从创建的对象。

内建对象:内建在JavaScript语言里的对象,例如Array、Math和Date等。

宿主对象:由浏览器提供的对象。

3、模型:DOM中的"M"

    DOM中的”M“代表着”Model“(模型),但说它代表着”Map“(地图)也是可以的。但他们都是某种事物的表现形式。就像一个模型火车代表着一列真正的火车那样。DOM代表着加载到浏览器窗口的当前网页。浏览器提供了网页的地图(或者说模型),而我们可以通过JavaScript去读取这张地图。

    要想从DOM获得信息,必须先把各种表示和描述文档的"图例"弄明白。

    DOM把一份文档表示为一颗树,这是我们理解和运用这一模型的关键。更具体地说,DOM把文档表示为一颗家谱树。

    家谱树本身又是一种模型。家谱树的典型做法是表示一个人类家族的谱系,并使用parent(父)、child(子)、sibling(兄弟)等记号来表明家族成员之间的关系。

    家谱树模型本身非常适合用来表示一份用(X)HTML语言编写出来的文档。

下面是一份非常基本的网页,内容是一份购物清单。

<!DOCTYPE html>
<html lang = "en">
	<head>
		<meta charset = "utf-8"/>
		<title>Shopping list</title>
	</head>
	<body>	
		<h1>What to buy</h1>
		<p title= "a gentle reminder">Don't forget to buy this stuff.</p>
		<ul id = "purchases">
			<li>a tin of beans</li>
			<li class = "sale">Cheese</li>
			<li class = "sale important">Milk</li>
		</ul>
	</body>
</html>

我们来分析一下:在DOCTYPE之后,一个打开了的<html>标签标识了整个文档的开始,这个网页里的所有其他元素都包含在这个元素里面,这表示它至少是一个父亲(parent)。又因为所有其他的元素都包含在其内部,所以这个<html>标签既没有父亲,也没有兄弟,这个<html>就是树根。

    根元素是html,不管从哪个角度来看,html都是代表整个文档。

    接下来深入一层,我们发现有<head>和<body>两个分支。

.....

如果把一个文档的各个元素想象成一颗家谱树,我们就可以用同样的数据描述DOM,不过,与使用"家谱树"这个术语相比,把文档称为"节点树"更准确。

4、节点

    节点(node)表示网络中的一个连接点。一个网络就是由一些节点构成的集合。

    原子是现实世界中的节点。文档是由节点构成的集合,只不过此时的节点是文档树上的树枝和树叶而已。

    在DOM里有许多不同类型的节点。就像原子包含着亚原子颗粒那样,也有很多类型的DOM节点包含着其他类型的节点。先看其中的三种:元素节点、文本节点、属性节点。

    所谓元素节点:DOM的原子就是元素节点(element node)。

    在上面那份"购物清单"文档时,我们使用了诸如<body>、<p>和<ul>之类的元素。如果把Web上的文档比作大厦,元素就是建造这座大厦的砖块,这些元素在文档的布局形成了文档的结构。标签的名字就是元素的名字。文本段落元素的名字是"p",无序清单元素的名字是"ul",列表项的名字是"li"。

    元素可以包含其他元素。在上面那份"购物清单"文档里,所有的列表项元素都包含在一个无序清单元素的内容。


    所谓"文本节点":在上面那份"购物清单"文档里,<p>元素包含着”Don't forget to buy this stuff.“它是一个文本节点。(text node)在XHTML文档中,文本节点总是被包含在元素节点的内部。但并非所有的元素节点都包含有文本节点。

    所谓"属性节点":属性节点用来对元素做出更具体的描述。几乎所有元素都有一个title属性,而我们可以利用这个属性对包含在元素里的东西做出准确的描述:

    <p title = "a gentle reminder">Don't forget to buy this stuff.</p>


CSS

    DOM并不是与网页结构打交道的唯一技术,我们还可以通过CSS(层叠样式表)告诉浏览器怎么显示一份文档的内容。

    类似JavaScript脚本,对样式的声明既可以嵌在文档的<head>部分(<style>标签之间,也可以放在另外一个样式表文件里)。CSS声明元素样式的语法与JavaScript函数的定义语法很相似:

selector{

    property:value;

}

在样式声明里,我们可以定义浏览器在显示元素时使用的颜色、字体和字号,如下:

p{

color:yellow;

font-family:"arial",sans-serif;

font-size:1.2em}

        继承(inheritance)是CSS技术中的一项强大功能,例如:如果我们为body元素定义了一些颜色或字体,包含在body所有元素都将自动获得哪些样式。

       在某些场合,当样式应用于一份文档时,我们其实只想让那些样式作用于某个特定的元素。

        为了把某一个或几个元素与其他元素区别开来,需要使用class属性或id属性。

        1、class属性

你可以在所有元素上任意应用class属性:

<p class = "special">This paragraph has the special class </p>

<h2  class = "special">So does this headline</h2>

在样式表里,可以像下面这样为class属性值相同的所有元素定义同一种样式:

.special{

    font-style:italic;

}

还可以像下面这样利用class属性为一种特定类型的元素定义一种特定的样式:

h2.special{

text-transform:uppercase;

}

    2、id属性

id属性的用途是给网页里的某个元素加上一个独一无二的标识符,如下:

<ul id = "purchases">

在这样的样式表里,可以像下面这样为有特定id属性值的元素定义一种独享的样式:

#purchases{

    border: 1px solid white;

    background-color:#333

    color:#ccc;

    padding:1em

}

尽管id本身只能使用一次,样式表还是可以利用id属性为包含在该特定元素里的其他元素定义样式。例如:

#purchases li{

    font-weight:bold;

}

id属性就像是一个挂钩,它一头连着文档里的某个元素,另一头连着CSS样式表里的某个样式,DOM也可以使用这种挂钩。


获取元素

有3种方法可以获取元素节点,分别是通过元素id、通过标签名字和类名字来获取。

1、getElementById

    DOM提供了一个名为getElementById的方法,这个将返回一个与那个有着给定id属性值得元素节点对应的对象。但是请注意:JavaScript区分大小写。

    它是document对象所特有的函数,在脚本代码里,函数名的后面必须有一对圆括号,这对圆括号包含着函数的参数。getElementById方法只有一个参数:就是你想要获得那个元素的id属性的值,这个值必须放在单引号或者双引号里。

document.getElementById(id);

下面是一个例子:

document.getElementById("purchases")

       这个调用将返回一个对象,这个对象对应着document对象里的独一无二的元素,那个元素的HTMLid属性值是purchases。你可以用typeof操作符来验证这一点。typeof操作符可以告我们它的操作数是一个字符串、数值、函数、布尔值还是对象。

如下:

<!DOCTYPE html>
<html lang = "en">
	<head>
		<meta charset = "utf-8"/>
		<title>Shopping list</title>
	</head>
	<body>	
		<h1>What to buy</h1>
		<p title= "a gentle reminder">Don't forget to buy this stuff.</p>
		<ul id = "purchases">
			<li>a tin of beans</li>
			<li class = "sale">Cheese</li>
			<li class = "sale important">Milk</li>
		</ul>
		<script>
		alert(typeof document.getElementById("purchases"));
		</script>
	</body>
</html>

运行之后,会弹出一个alert对话框,报告书document.getElementById("purchases")的类型-它是一个对象。

事实上,文档中的每一个对象都是一个对象。利用DOM提供的方法可以得到任何一个对象。但是我们没有必要为为文档中的每一个元素都定义一个独一无二的id值。DOM提供了另一个方法来获取那些没有id属性的对象。

    2、getElementsByTagName

getElementByTagName方法返回一个对象数组,每个对象分别对应着文档里有着给定标签的一个元素。类似于getElementById,这个方法也是只有一个参数的函数,它的参数是标签的名字:

element.getElementsByTagName(tag)

它与getElementById方法有许多类似之处,但是它返回的是一个数组。

例子:

document.getElementByTagName("li"),这个调用将返回一个对象数组,每个对象分别对应着document对象中的一个列表项元素。与任何其他的数组一样,我们可以利用length属性查出这个数组里的元素个数。

我们把原来的里中的<script>标签中的alert语句替换成这条语句:

<!DOCTYPE html>
<html lang = "en">
	<head>
		<meta charset = "utf-8"/>
		<title>Shopping list</title>
	</head>
	<body>	
		<h1>What to buy</h1>
		<p title= "a gentle reminder">Don't forget to buy this stuff.</p>
		<ul id = "purchases">
			<li>a tin of beans</li>
			<li class = "sale">Cheese</li>
			<li class = "sale important">Milk</li>
		</ul>
		<script>
			alert(document.getElementsByTagName("li").length);
		</script>
	</body>
</html>

你会看到这份文档里的列表项元素的个数:3。这个数组里的每个元素都是一个对象。可以利用循环语句和typeof操作符去遍历这个数组来验证这一点。例如:

for(var i = 0;i<document.getElementsByTagName("li").length;i++){

alert(typeof document.getElementByTagName("li")[i]);

}

注意:即使在整个文档里这个标签里只有一个元素,getElementByTagName也返回一个数组,此时,那个数组的长度是1。

为了改善代码的可读性;只要把document.getElementByTagName("li")赋值给一个变量即可。

请把<script>标签中的alert语句替换成下面这些语句:

var items = document.getElementsByTagName("li");

for(var i =0;i<items.length;i++){

    alert(typeof items[i])

}

即:

<!DOCTYPE html>
<html lang = "en">
	<head>
		<meta charset = "utf-8"/>
		<title>Shopping list</title>
	</head>
	<body>	
		<h1>What to buy</h1>
		<p title= "a gentle reminder">Don't forget to buy this stuff.</p>
		<ul id = "purchases">
			<li>a tin of beans</li>
			<li class = "sale">Cheese</li>
			<li class = "sale important">Milk</li>
		</ul>
		<script>
			var items = document.getElementsByTagName("li");

			for(var i =0;i<items.length;i++){

			alert(typeof items[i])

			}
		</script>
	</body>
</html>

    我们可以到有三个alert对话框;显示消息都是”object“。

此外:

        getElementsByTagName允许把一个通配符作为它的参数,而这意味着文档里的每个元素都将在这个函数所返回的数组里占有一席之地。通配符(星号字符"*")必须放在引号里,这是为了让通配符与乘法操作符有所区别。如果你想知道某份文档中有多少个元素节点,像下面这样使用通配符即可:

    alert(document.getElementsByTagName("*").length);

还可以:

    把getElementsByTagName()与getElementById()结合起来一起使用。如果只想知道id属性值是purchases的元素包含了多少个列表项,必须通过一个更具体的对象去调用这个方法,如下:

        var shopping = document.getElementById("purchases");

        var items = shopping.getElementsByTagName("*");

这两条语句执行完毕之后,items数据将只包含id属性值是purchase的无序清单里的元素。具体到这个例子,items数组里的长度刚好与这份文档里的列表项元素的总数相等:

alert(items.length);

如果还需要跟多的证据,下面这些语句将证明items数组里的每个值确实一个对象:

for(var i = 0;i<items.length;i++){

    alert(typeof item[i]);

}

3、getElementsByClassName

HTML5 DOM中新增了一个令人期待已久的方法:getElementsByClassName。这个方法让我们能够通过class属性中的类名来访问元素。

与getElementsByTagName()方法类似,getElementsByClassName也是只接受一个参数,就是类名:

    getElementsByClassName(class)

这个方法与getElementsByTagName类似,都是一个具有相同类名的元素的数组。下面这行代码返回的就是一个数组,其中包含类名为"sale"的所有元素:

document.getElementsByClassName("sale");

使用这个方法还可以查找那些带有多个类名的元素。要指定多个类名,只要在字符串参数中用空格分隔类名即可。例如:

在<script>标签中添加这行alert代码:

alert(document.getElementsByClassName("important  sale").length);

你会发现只有一个元素同时带有"important"和"sale"类名。注意:即使在元素的class属性中,类名的顺序是"sale important"而非参数指定的"important sale",也会照样匹配该元素。不仅类名的实际顺序不重要,就算元素还带有更多的类名也没有关系。

    与使用getElementsByTagName一样,也可以组合使用getElementsByClassName和getElementById。如果你想知道在id位"purchases"的元素中有多少类名包含"sale"列表项。可以先找到那个特定的对象,然后再调用getElementsByClassName:

var shopping = document.getElementById("purchases");

var sales = shopping.getElementsByClassName("sale");

这样,sales数组中就包含的就只是位于"purchases"列表项中的带有"sale"类的元素。

运行代码:alert(sales.length);。


盘点知识点:

  • 一份文档就是一颗节点树
  • 节点分为不同的类型:元素节点、属性节点和文本节点。
  • getElementById将返回一个对象,该对象对应着文档里的一个特定元素节点。
  • getElementsByTagName和getElementsByClassName将返回一个对象数组,它们分别对应着文档里的一组特定的元素节点。
  • 每个节点都是一个对象。

5、获取和设置属性

我们有三种获取特定元素的方法,得到需要的元素之后,我们就可以使用getAttribute方法获取它的各个属性。setAttribute()方法则可以更改属性节点的值。

getAttribute方法不属于document对象,所有不能通过document对象来调用。它之只能通过元素节点对象调用。可以通过getElementsByTagName方法合用,获取每个<p>元素的title属性,如下所示:

var paras = document.getElementsByTagName("p");

for(var i = 0;i < paras.length;i++){

       alert(paras[i].getAttribute("title"));

}

例如:

<!DOCTYPE html>
<html lang = "en">
	<head>
		<meta charset = "utf-8"/>
		<title>Shopping list</title>
	</head>
	<body>	
		<h1>What to buy</h1>
		<p title= "a gentle reminder">Don't forget to buy this stuff.</p>
		<ul id = "purchases">
			<li>a tin of beans</li>
			<li class = "sale">Cheese</li>
			<li class = "sale important">Milk</li>
		</ul>
		<script>
			var paras = document.getElementsByTagName("p");
			for(var i = 0;i < paras.length;i++){
				alert(paras[i].getAttribute("title"));
			}
		</script>
	</body>
</html>

会弹出什么呢?

在文档文件中,只有一个p元素,并且它有title属性。假如这份文档有更多个<p>元素,并且没有title属性,则getAttribute("title")方法会返回null值。在JavaScript里面,null的含义是"没有值"。我们可以试试再添加一个<p>标签;

<p>This is just a test </p>

如:

<!DOCTYPE html>
<html lang = "en">
	<head>
		<meta charset = "utf-8"/>
		<title>Shopping list</title>
	</head>
	<body>	
		<h1>What to buy</h1>
		<p title= "a gentle reminder">Don't forget to buy this stuff.</p>
		<p>This is just a test </p>
		<ul id = "purchases">
			<li>a tin of beans</li>
			<li class = "sale">Cheese</li>
			<li class = "sale important">Milk</li>
		</ul>
		<script>
			var paras = document.getElementsByTagName("p");
			for(var i = 0;i < paras.length;i++){
				alert(paras[i].getAttribute("title"));
			}
		</script>
	</body>
</html>

重新加载这个页面。会出现什么呢?


我们可以修该脚本,让它只在title属性有值时才弹出消息。我们增加一条if语句来检查getAttribute的返回值是不是null。

如下:

var paras  = document.getElementsByTagName("p");

for(var i = 0;i <paras.length;i++){

    var title_text =paras[i].getAttribute("title");

    if(title_text != null)

    alert(title_texg);

}

重新加载,又会出现什么呢?


setAttribute

它允许我们对属性节点的值做出修该。与getAttribute一样。setAttribute也只能用于元素节点:

    object.setAttribute(attribute,value)

例子:

var shopping = document.getElementById("purchases");
alert (shopping.getAttribute("title"));
shopping.setAttribute("title","a list of goods");
alert (shopping.getAttribute("title"));

运行之后,会出现什么呢?

还有一个细节:通过setAttribute对文档做出修改后,在通过浏览器的view source(查看源代码)选项去查看文档的源代码时看到的仍然是改变前的属性值,也就是说,setAttribute做出的修该不会反映在文档本身的源代码里。这种“表里不一”的现象源自DOM的工作模式:先加载文档的静态内容,在动态刷新,动态刷新不影响文档的静态内容。这是DOM的真正威力:对页面内容进行刷新却不需要在浏览器里刷新页面。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值