关闭

关闭

关闭

封号提示

内容

首页 Javascript_DOM编程艺术翻译版.pdf

Javascript_DOM编程艺术翻译版.pdf

Javascript_DOM编程艺术翻译版.pdf

上传者: Cherry玉凤 2017-06-06 评分 0 0 0 0 0 0 暂无简介 简介 举报

简介:本文档为《Javascript_DOM编程艺术翻译版pdf》,可适用于IT/计算机领域,主题内容包含第章DOM本章内容节点的概念四个非常实用的DOM方法:getElementById、getElementsByTagName、getAttribut符等。

第章DOM本章内容节点的概念四个非常实用的DOM方法:getElementById、getElementsByTagName、getAttribute和setAttribute终于要与DOM面对面了。能够向大家介绍DOM是笔者的荣幸我非常乐于带领大家通过DOM的眼睛去看世界。文档:DOM中的“D”DOM是“DocumentObjectModel”(文档对象模型)的首字母缩写。如果没有document(文档)DOM也就无从谈起。当创建了一个网页并把它加载到Web浏览器中时DOM就在幕后悄然而生。它将根据你编写的网页文档创建一个文档对象。在人类语言中“对象”这个词的含义往往不那么明确和具体它几乎可以用来称呼任何一种客观存在的事物。但在程序设计语言中“对象”这个词的含义非常明确和具体。对象:DOM中的“O”在上一章的末尾我们向大家展示了几个JavaScript对象的例子。你们应该还记得“对象”是一种独立的数据集合。与某个特定对象相关联的变量被称为这个对象的属性可以通过某个特定对象去调用的函数被称为这个对象的方法。JavaScript语言里的对象可以分为三种类型:用户定义对象(userdefinedobject):由程序员自行创建的对象。本书不讨论这种对象。内建对象(nativeobject):内建在JavaScript语言里的对象如Array、Math和Date等。宿主对象(hostobject):由浏览器提供的对象。在JavaScript语言的发展初期程序员在编写JavaScript脚本时经常需要用到一些非常重要的宿主对象它们当中最基础的是window对象。window对象对应着浏览器窗口本身这个对象的属性和方法通常被统称为BOM(浏览器对象模型)但我觉得称之为WindowObjectModel(窗口对象模型)更为贴切。BOM向程序员提供了windowopen和windowblur等方法你们在上网冲浪时看到的各种弹出窗口和下拉菜单其数量之多已经到了泛滥成灾的地步几乎都是由这些方法负责创建和处理的。难怪JavaScript会有一个不好的名声!值得庆幸的是在这本书里我们不需要与BOM打太多的交道。我们将把注意力集中在浏览器窗口的内部而不是浏览器窗口本身。我们将着重探讨如何对网页的内容进行处理而用来实现这一目标的载体就是document对象。在本书的后续内容里我们将尽可能地只讨论document对象的属性和方法。现在我们已经对DOM中的字母“D”(document文档)和字母“O”(object对象)做了解释那么字母“M”又代表着什么呢?模型:DOM中的“M”DOM中的“M”代表着“Model”(模型)但说它代表着“Map”(地图)也未尝不可。模型也好地图也罢它们的含义都是某种事物的表现形式。就像一个模型火车代表着一列真正的火车、一张城市街道图代表着一个实际存在的城市那样DOM代表着被加载到浏览器窗口里的当前网页:浏览器向我们提供了当前网页的地图(或者说模型)而我们可以通过JavaScript去读取这张地图。既然是地图就必须有诸如方向、等高线和比例尺之类的记号。要想看懂和使用地图就必须知道这些记号的含义和用途这个道理同样适用于DOM。要想从DOM获得信息我们必须先把各种用来表示和描述一份文档的记号弄明白。DOM把一份文档表示为一棵树(这里所说的“树”是数学意义上的概念)这是我们理解和运用这一模型的关键。更具体地说DOM把文档表示为一棵家谱树。家谱树本身又是一种模型。家谱树的典型用法是表示一个人类家族的谱系并使用parent(父)、child(子)、sibling(兄弟)等记号来表明家族成员之间的关系。家谱树可以把一些相当复杂的关系简明地表示出来:一位特定的家族成员既是某些成员的父辈又是另一位成员的子辈同时还是另一位成员的兄弟。类似于人类家族谱系的情况家谱树模型也非常适合用来表示一份用(X)HTML语言编写出来的文档。请看下面这份非常基本的网页它的内容是一份购物清单。这份文档可以用图中的模型来表示。我们来分析一下这个网页的结构。这种分析不仅可以让我们了解它是由哪些元素构成的还可以让我们了解为什么图中的模型可以如此完美地把它表示出来。在对Doctype做出声明后这份文档首先打开了一个<html>标签而这个网页里的所有其他元素都包含在这个元素里。因为所有其他的元素都包含在其内部所以这个<html>标签既没有父辈也没有兄弟。如果这是一棵真正的树的话这个<html>标签显然就是树根。图把网页中的元素表示为一棵家谱树这正是图中的家谱树以html为根元素的原因。毫无疑问html元素完全可以代表整个文档。如果在这份文档里更深入一层我们将发现<head>和<body>两个分枝。它们存在于同一层次且互不包含所以它们是兄弟关系。它们有着共同的父元素<html>但又各有各的子元素所以它们本身又是其他一些元素的父元素。<head>元素有两个子元素:<meta>和<title>(这两个元素是兄弟关系)。<body>元素有三个子元素:<h>、<p>和<ul>(这三个元素是兄弟关系)。如果继续深入下去我们将发现<ul>也是一个父元素。它有三个子元素它们都是<li>元素。利用这种简单的家谱关系记号我们可以把各元素之间的关系简明清晰地表达出来。例如<h>和<ul>之间是什么关系?答案是它们是兄弟关系。那么<body>和<ul>之间又是什么关系?<body>是<ul>的父元素<ul>是<body>的一个子元素。如果把各种文档元素想像成一棵家谱树上的各个节点的话我们就可以用同样的记号来描述DOM。不过与使用“家谱树”这个术语相比把一份文档称为一棵“节点树”更准确。节点节点(node)这个名词来自网络理论它代表着网络中的一个连接点。网络是由节点构成的集合。在现实世界里一切事物都由原子构成。原子是现实世界的节点。但原子本身还可以进一步分解为更细小的亚原子微粒。这些亚原子微粒同样是节点。DOM也是同样的情况。文档也是由节点构成的集合只不过此时的节点是文档树上的树枝和树叶而已。在DOM里存在着许多不同类型的节点。就像原子包含着亚原子微粒那样有些DOM节点类型还包含着其他类型的节点。元素节点DOM的原子是元素节点(elementnode)。在描述刚才那份“购物清单”文档时我们使用了诸如<body>、<p>和<ul>之类的元素。如果把Web上的文档比作一座大厦元素就是建造这座大厦的砖块这些元素在文档中的布局形成了文档的结构。各种标签提供了元素的名字。文本段落元素的名字是“p”无序清单元素的名字是“ul”列表项元素的名字是“li”。元素可以包含其他的元素。在我们的“购物清单”文档里所有的列表项元素都包含在一个无序清单元素的内部。事实上没有被包含在其他元素里的唯一元素是<html>元素。它是我们的节点树的根元素。.文本节点元素只是不同节点类型中的一种。如果一份文档完全由一些空白元素构成它将有一个结构但这份文档本身将不会包含什么内容。在网上内容决定着一切没有内容的文档是没有任何价值的而绝大多数内容都是由文本提供的。在“购物清单”例子里<p>元素包含着文本“Don’tforgettobuythisstuff”。它是一个文本节点(textnode)。在XHTML文档里文本节点总是被包含在元素节点的内部。但并非所有的元素节点都包含有文本节点。在“购物清单”文档里<ul>元素没有直接包含任何文本节点它包含着其他的元素节点(一些<li>元素)后者包含着文本节点。.属性节点还存在着其他一些节点类型。例如注释就是另外一种节点类型。但我们这里还想向大家再多介绍一种节点类型。元素都或多或少地有一些属性属性的作用是对元素做出更具体的描述。例如几乎所有的元素都有一个title属性而我们可以利用这个属性对包含在元素里的东西做出准确的描述:在DOM中title="agentlereminder"是一个属性节点(attributenode)如图所示。因为属性总是被放在起始标签里所以属性节点总是被包含在元素节点当中。并非所有的元素都包含着属性但所有的属性都会被包含在元素里。图一个元素节点它包含着一个属性节点和一个文本节点在前面的“购物清单”示例文档里我们可以清楚地看到那个无序清单元素(<ul>)有个id属性。如果曾经使用过CSS你们对id和class之类的属性应该不会感到陌生。不过为了照顾那些对CSS还不太熟悉的读者我们下面将简要地重温几个最基本的CSS概念。.CSS:层叠样式表DOM并不是人们与网页的结构打交道的唯一手段。我们还可以通过CSS(层叠样式表)告诉浏览器应该如何显示一份文档的内容。类似于JavaScript脚本对样式的声明既可以嵌在文档的<head>部分(这需要用到<style>标签)也可以放在另外一个样式表文件里。利用CSS对某个元素的样式做出声明的语法与JavaScript函数的定义语法很相似:在样式声明里我们可以对浏览器在显示各有关元素时使用的颜色、字体和字号做出定义如下所示:继承(inheritance)是CSS技术中的一项强大功能。类似于DOMCSS也把文档的内容视为一棵节点树。节点树上的各个元素将继承其父元素的样式属性。例如如果我们为body元素定义了一些颜色或字体包含在body元素里的所有元素都将自动获得也就是继承那些样式:这些颜色将不仅作用于那些被直接包含在<body>标签里的内容还将作用于那些嵌套在body元素内部的所有元素。这里是把刚才定义的样式应用在“购物清单”示例文档上而得到的网页显示效果。在某些场合当把样式应用于一份文档时我们其实只想让那些样式只作用于某个特定的元素。例如我们只想让某一段文本变成某种特殊的颜色和字体但不想让其他段落受到影响。为了获得如此精细的控制我们将需要在文档里插入一些能够把这段文本与其他段落区别开来的特殊标志。为了把某一个或某几个元素与其他元素区别开来我们需要使用class属性或id属性之一。lclass属性所有的元素都有class属性不同的元素可以有同样的class属性值。如下所示:在样式表里我们可以像下面这样为class属性值相同的所有元素定义一种共享的样式:我们还可以像下面这样利用class属性为一种特定类型的元素定义一种独享的样式:lid属性id属性的用途是给网页里的某个元素加上一个独一无二的标识符如下所示:在样式表里我们可以像下面这样为有着特定id属性值的元素定义一种独享的样式:每个元素只能有一个id属性值不同的元素必须有不同的id属性值。不过我们可以在样式表里像下面这样利用id属性为包含在某给定元素里的其他元素定义样式而如此定义出来的样式将只作用于包含在这个给定元素里的有关元素:这里是把刚才利用id属性定义的样式应用在“购物清单”示例文档上而得到的网页显示效果。id属性就像是一个挂钩它一头连着文档里的某个元素另一头连着CSS样式表里的某个样式。DOM也可以使用这种挂钩事实上有不少DOM操作必须借助于这种挂钩才能完成。getElementById()方法DOM提供了一个名为getElementById()的方法这个方法将返回一个与那个有着给定id属性值的元素节点相对应的对象。请注意JavaScript语言区分字母的大小写情况所以大家在写出“getElementById”时千万不要把大小写弄错了。如果把它错写成“GetElementById”或“getElementbyid”你将无法得到你真正想要的东西。这个方法是与document对象相关联的函数。在脚本代码里函数名的后面必须跟有一组圆括号这组圆括号包含着函数的参数。getElementById()方法只有一个参数:你想获得的那个元素的id属性值这个id值必须放在单引号或双引号里。下面是一个例子:这个调用将返回一个对象这个对象对应着document对象里的一个独一无二的元素那个元素的HTMLid属性值是purchases。再说一遍getElementById()方法将返回一个对象。你们可以用typeof操作符来验证这一点。typeof操作符可以告诉我们它的操作数是不是一个字符串、数值、函数、布尔值或对象。下面是把一些JavaScript语句插入到前面给出的“购物清单”文档之后得到的一份代码清单新增的代码(黑体字部分)出现在<body>结束标签之前。顺便说一句我本人并不赞成把JavaScript代码直接嵌入一份文档的做法但它不失为一种简便快捷的测试手段:把上面这些代码保存为一个XHTML文件。当在你们的Web浏览器里加载这个XHTML文件时屏幕上将弹出一个如下所示的alter对话框它向你们报告documentgetElementById("purchases")的类型它是一个对象。不仅如此如果用上述办法去检查其他元素节点的类型你们也会看到类似的alert对话框。事实上文档中的每一个元素都对应着一个对象。利用DOM提供的方法我们可以把与这些元素相对应的任何一个对象筛选出来。一般来说我们用不着为文档里的每一个元素都分别定义一个独一无二的id值那也太小题大做了。要知道即使某个元素没有独一无二的id值我们也可以利用DOM提供的另一个方法把与之对应的对象准确无误地筛选出来。getElementsByTagName()方法getElementsByTagName()方法将返回一个对象数组每个对象分别对应着文档里有着给定标签的一个元素。类似于getElementById()这个方法也是只有一个参数的函数它的参数是(X)HTML标签的名字:它与getElementById()方法有许多相似之处但有一点要特别提醒大家注意:getElementsByTagName()方法返回的是一个数组你们在编写脚本时千万注意不要把这两个方法弄混了。下面是一个例子:这个调用将返回一个对象数组每个对象分别对应着document对象中的一个列表项(li)元素。与任何其他的数组一样我们可以利用length属性查出这个数组里的元素个数。首先在上一小节给出的XHTML示例文档里把<script>标签中的alter语句替换为下面这条语句:然后用浏览器里重新加载那个XHTML文件你们就会看到这份示例文档里的列表项元素的个数:。这个数组里的每个元素都是一个对象。可以通过利用一个循环语句和typeof操作符去遍历这个数组的办法来验证这一点。例如你们可以试试下面这个for循环:请注意即使在整个文档里只有一个元素有着给定的标签名getElementsByTagName()方法也将返回一个数组。此时那个数组的长度是。你们或许早就觉得用键盘反复敲入documentgetElementsByTagName("li")是件很麻烦的事情而这些长长的字符串会让代码变得越来越难以阅读。有个简单的办法可以减少不必要的打字量并改善代码的可读性:只要把documentgetElementsByTagName("li")赋值给一个变量即可。请在上一小节给出的XHTML示例文档里把<script>标签中的alter语句替换为下面这些语句:现在当用浏览器里重新加载那个XHTML文件时你们将看到三个alert对话框显示在这三个alert对话框里的消息都是“object”。getElementsByTagName()方法允许我们把一个通配符当为它的参数而这意味着文档里的每个元素都将在这个函数所返回的数组里占有一席之地。通配符(星号字符“*”)必须放在引号里这是为了让通配符与乘法操作符有所区别。如果你想知道某份文档里总共有多少个元素节点像下面这样以通配符为参数去调用getElementsByTagName()方法是最简便的办法:我们还可以把getElementById()和getElementsByTagName()方法结合起来运用。例如我们刚才给出的几个例子都是通过document对象调用getElementsByTagName()方法的如果只想知道其id属性值是purchase的元素包含着多少个列表项(li)的话你就必须通过一个更具体的对象去调用这个方法如下所示:在这两条语句执行完毕后items数组将只包含其id属性值是purchase的无序清单里的元素。具体到我们这个例子items数组的长度刚好与这份文档里的列表项元素的总数相等:如果还需要更多的证据下面这些语句将证明items数组里的每个值确实是一个对象:趁热打铁在看过那么多显示着单词“object”的alert对话框后你们很可能不愿意再看到它。如果真是如此我的目的也就达到了我想通过这些alert对话框强调这样一个事实:文档中的每个元素节点都是一个对象。我现在要告诉大家的是这些对象中的每个都为我们准备了一系列非常有用的方法而这一切当然都要归功于DOM。利用这些已经预先定义好的方法我们不仅可以检索出关于文档里的任何一个对象的信息甚至还可以改变某些元素的属性。下面是对本章此前学习内容的一个简要总结:一份文档就是一棵节点树。节点分为不同的类型:元素节点、属性节点和文本节点等。getElementById()方法将返回一个对象该对象对应着文档里的一个特定的元素节点。getElementsByTagName()方法将返回一个对象数组它们分别对应着文档里的一个特定的元素节点。这些节点中的每个都是一个对象。接下来我们将向大家介绍几个与这些对象相关联的属性和方法。getAttribute()方法至此我们已经向大家介绍了两种检索特定元素节点的办法:一种是使用getElementById()方法另一种是使用getElementsByTagName()方法。在找到那个元素后我们就可以利用getAttribute()方法把它的各种属性的值查询出来。getAttribute()方法是一个函数。它只有一个参数你打算查询的属性的名字:不过getAttribute()方法不能通过document对象调用这与我们此前介绍过的其他方法不同。我们只能通过一个元素节点对象调用它。例如你可以把它与getElementsByTagName()方法结合起来去查询每个<p>元素的title属性如下所示:如果把上面这段代码插入到前面给出的“购物清单”示例文档的末尾并在Web浏览器里重新加载这个页面屏幕上将弹出一个显示着文本消息“agentlereminder”的alter对话框。在“购物清单”文档里只有一个带有title属性的<p>元素。假如这份文档还有一个或更多个不带title属性的<p>元素则相应的getAttribute("title")调用将返回。是JavaScript语言中的空值其含义是“你说的这个东西不存在”。如果你们想亲自验证一下这件事请先把下面这段文本插入到“购物清单”文档中的现有文本段落之后:然后重新加载这个页面。这一次你们将看到两个alter对话框而第二个对话框将是一片空白或者是只显示着单词“”具体情况要取决于你的Web浏览器将如何显示值。可以修改我们的脚本让它只在title属性存在时才弹出一条消息。我们将增加一条if语句来检查getAttribute()方法的返回值是不是。趁着这个机会我们还增加了几个变量以提高脚本的可读性:现在如果重新加载这个页面你们将只会看到一个显示着“agentlereminder”消息的alter对话框如下所示。我们甚至可以把这段代码缩得更短一些。当检查某项数据是否是值时我们其实是在检查它是否存在。这种检查可以简化为直接把被检查的数据用做if语句的条件。if(something)与if(something!=)完全等价但前者显然更为简明。此时如果something存在则if语句的条件将为真如果something不存在则if语句的条件将为假。具体到这个例子只要我们把if(titletext!=)替换为if(titletext)我们就可以得到更简明的代码。此外为了进一步增加代码的可读性我们还可以趁此机会把alter语句与if语句写在同一行上这可以让它们更接近于我们日常生活中的英语句子:setAttribute()方法我们此前介绍给大家的所有方法都只能用来检索信息。setAttribute()方法与它们有一个本质上的区别:它允许我们对属性节点的值做出修改。类似于getAttribute()方法setAttribute()方法也是一个只能通过元素节点对象调用的函数但setAttribute()方法需要我们向它传递两个参数:在下面的例子里第一条语句将把id属性值是purchase的元素检索出来第二条语句将把这个元素的title属性值设置为alistofgoods:我们可以利用getAttribute()方法来证明这个元素的title属性值确实发生了变化:上面这些语句将在屏幕上弹出两个alert对话框:第一个alter对话框出现在setAttribute()方法被调用之前它将是一片空白或显示着单词“”第二个出现在title属性值被设置之后它将显示着“alistofgoods”消息。在上例中我们设置了一个现有节点的title属性但这个属性原先并不存在。这意味着我们发出的setAttribute()调用实际完成了两项操作:先把这个属性创建出来然后再对其值进行设置。如果我们把setAttribute()方法用在元素节点的某个现有属性上这个属性的当前值将被覆盖。在“购物清单”示例文档里<p>元素已经有了一个title属性这个属性的值是agentlereminder。我们可以用setAttribute()方法来改变它的当前值:上面这段代码将先从文档里把已经带有title属性的<p>元素全部检索出来然后把它们的title属性值全部修改为brandnewtitletext。具体到“购物清单”文档属性值agentlereminder将被覆盖。这里有一个非常值得关注的细节:通过setAttribute()方法对文档做出的修改将使得文档在浏览器窗口里的显示效果和或行为动作发生相应的变化但我们在通过浏览器的viewsource(查看源代码)选项去查看文档的源代码时看到的仍将是原来的属性值也就是说setAttribute()方法做出的修改不会反映在文档本身的源代码里。这种“表里不一”的现象源自DOM的工作模式:先加载文档的静态内容、再以动态方式对它们进行刷新动态刷新不影响文档的静态内容。这正是DOM的真正威力和诱人之处:对页面内容的刷新不需要最终用户在他们的浏览器里执行页面刷新操作就可以实现。小结在这一章里我们向大家介绍了DOM提供的四个方法:getElementById()方法getElementsByTagName()方法getAttribute()方法setAttribute()方法这四个方法是将要编写的许多DOM脚本的基石。DOM还提供了许多其他的属性和方法如nodeName、nodeValue、chileNodes、nextSibling和parentNode等但现在还不是它们出场的时候我打算在本书后面的有关章节中选择一些适当的时机把它们依次介绍给大家。我在这里列出它们的目的只是为了激起大家的学习兴趣。本章内容比较偏重于理论。在看过那么多的alter对话框之后相信大家都迫不及待地想通过其他一些东西去进一步了解和测试DOM而我也正想通过一个案例来进一步展示DOM的强大威力。在下一章中我将带领大家利用本章介绍的四个DOM方法去创建一个基于JavaScript的图片库。第章案例研究:JavaScript美术馆现在是时候利用DOM去完成一些简单的任务了。在这一章中我将带领大家用JavaScript和DOM去建立一个图片库并将其称为“JavaScript美术馆”。我们将按照以下步骤来完成这一案例:编写一份优秀的标记语言文档。编写一个JavaScript函数以显示用户想要查看的图片。在标记语言文档里触发一个调用JavaScript图片显示的函数。对这个JavaScript函数的功能进行扩展。这需要用到几个新的DOM方法。把一些图片发布到网上的办法很多。最容易想到的办法是把所有的图片都放到同一个网页里。不过如果你打算发布的图片比较多的话这个页面很快就会因为变得过于巨大而失去吸引力。要知道虽然这种网页本身的HTML代码不会多到哪儿去但算上那些图片可就不一样了。我们必须面对的现实是:数据量越大网页的下载时间就越长但愿意等待很长时间去下载一个网页的人却没有几个。因此为每张图片分别创建一个网页的解决方案显然更值得考虑。你的图片库将不再是一个体积庞大、难以下载的网页而是许多尺寸合理、便于下载和浏览的页面。不过这一解决方案并非尽善尽美:首先为每张图片分别制作一个网页需要花费不少的时间和精力其次需要在每个网页上提供一些链接来给出当前图片在整个图片库里的位置以方便人们从当前图片转到其他的图片。如果你想两全其美利用JavaScript来创建图片库将是最佳的选择:把整个图片库的浏览链接集中安排在你的图片库主页里只在用户点击了这个主页里的某个图片链接时才把相应的图片传送给他。编写标记语言文档为了完成“JavaScript美术馆”案例我特意用数码相机拍摄了几张照片并把它们修整成最适合于用浏览器来查看的尺寸即像素宽像素高。第一项工作是为这些图片创建一个链接清单。因为我没打算让这些图片按照某种特殊的顺序排列所以将使用一个无序清单元素(<ul>)来列出那些链接。如果想让自己的图片按顺序排列的话应该使用一个排序清单元素(<ol>)去组织图片链接。下面就是我编写出来的HTML文档:我将把这份文档保存为galleryhtml文件并把图片集中保存在子目录images里。我的images子目录和galleryhtml文件位于同一个子目录下。在galleryhtml文件里无序清单元素中的每个链接分别指向不同的图片。在浏览器窗口里点击某个链接就可以转到相应的图片但从图片重新返回到链接清单目前还必须借助于浏览器的Back(后退)按钮。下面是这个基本的链接清单在浏览器窗口里的显示效果。这是一个相当令人满意的网页但它的默认行为还不太理想。下面是我觉得还需要改进的几个地方:当点击某个链接时我希望能留在这个网页而不是转到另一个窗口。当点击某个链接时我希望能在这个网页上同时看到那张图片以及原有的图片清单。下面是我为了实现上述希望而需要完成的几项改进:通过增加一个“占位符”图片的办法在这个主页上为图片预留一个浏览区域。在点击某个链接时将拦截这个网页的默认行为。在点击某个链接时将把“占位符”图片替换为与那个链接相对应的图片。我们先来解决“占位符”图片的问题。我选用了一个类似于名片的图片你们可以根据个人喜好来决定选用的图片即使选用一个空白图片也没问题。把下面这些代码插入到图片名单的末尾:我对这个图片的id属性进行了设置这将使我可以通过一个外部的样式表对图片的显示位置和显示效果加以控制。例如我可以让这个图片出现在链接清单的旁边而不是它的下方。我还可以在自己的JavaScript代码里使用这个id值。下面是这个页面在增加了“占位符”图片后的显示效果。现在我的HTML文档已经准备好了。接下来的工作是编写一些必要的JavaScript代码。编写JavaScript函数为了把“占位符”图片替换为想要查看的图片需要改变它的src属性。setAttribute()方法是完成这项工作的最佳选择而我将利用这个方法写一个函数。那个函数只有一个参数即我想查看的那张图片的链接它将通过改变“占位符”图片的src属性的办法将其替换为我想查看的那张图片。首先需要给函数起一个好的名字。我想让它既能提醒我这个函数的用途又足够简明扼要。我决定把这个函数命名为showPic()。还需要给这个函数的参数起一个名字我决定把它命名为whichpic:whichpic代表着一个元素节点具体地说那将是一个指向某个图片的<a>元素。我需要知道那个图片的文件路径这个路径可以通过在whichpic元素上调用getAttribute()方法的办法查出来只要把"href"作为参数传递给getAttribute()方法就可以知道那个图片的文件路径了:我将把这个路径存入一个变量以便在后面的语句里使用它。我决定把这个变量命名为source:接下来还需要把“占位符”图片检索出来这种事对getElementById()方法来说不过是小菜一碟:我不想重复敲入“documentgetElementById("placerholder")”这么长的字符串所以将把这个元素赋值给一个变量并将其命名为placerholder:现在已经声明并赋值了两个变量:source和placerholder。它们可以让我的脚本简明易读。我将使用setAttribute()方法对placerholder元素的src属性进行刷新。还记得吗这个方法有两个参数:一个是打算对之进行设置的属性另一个是这个属性的新属性值。具体到这个例子因为我想对src属性进行设置所以第一个参数是"src"至于第二个参数也就是src属性的新属性值我已经把它保存在source变量里了:这显然要比下面这么冗长的代码更容易阅读和理解:DOM之前的解决方案其实不使用setAttribute()方法也可以改变某个图片的src属性。setAttribute()方法是“第级DOM”(DOMLevel)的组成部分之一这个方法可以对任意元素节点的任意属性进行设置。在“第级DOM”出现之前程序员只能通过另外一种办法对一部分元素的属性进行设置这个办法至少在目前还可以用来改变某些属性的值。例如如果想改变某个输入元素的value属性可以使用如下所示的办法:这与下面这条语句的效果是等价的:类似的办法也可以用来改变图片的src属性。例如在我的图片库脚本里完全可以用下面这条语句来代替setAttribute()调用:我个人更喜欢使用setAttribute()方法。这起码可以让我不必费心去记忆哪些元素的哪些属性可以用哪些DOM之前的方法去设置。虽然用那些老办法可以毫无问题地对文档里的图片、表单和其他一些元素的属性进行设置但setAttribute()方法的优势在于它可以对文档中的任何一个元素的任何一个属性做出修改。“第级DOM”的另一个优势是可移植性更好。那些老方法只适用于Web文档DOM则适用于任何一种标记语言。虽然这种差异对我们这个例子没有影响但我希望大家能够牢牢记住这一点:DOM是一种适用于多种环境和多种程序设计语言的通用型API。如果想把从本书学到的DOM技巧运用在Web浏览器以外的应用环境里严格遵守“第级DOM”能够让你们避免与兼容性有关的任何问题。showPic()函数的代码清单下面是showPic()函数完整的代码清单:接下来的任务是把这个JavaScript函数与我们的HTML文档结合起来。JavaScript函数的调用我需要把刚编写出来showPic()函数与图片库HTML文档结合起来。最简单的办法是把这个函数用一组<script>标签插入到那个文档的<head>部分但我认为这种做法有点儿目光短浅:如果今后想把这同一函数用在多个页面上的话我将不得不反复多次地进行剪贴操作。为今后考虑更有远见的办法是先把这个函数存入一个外部文件然后在每一份需要用到这个函数的HTML文档的<head>部分插入一个链接来引用这个外部文件。以js作为文件扩展名把这个函数存入一个文本文件。完全可以把这种文件命名为你们喜欢的任何东西但我习惯于用这些文件所包含的函数的名字来命名它们我给这个文件起的名字是showPicjs。就像我刚才决定把所有的图片集中存放在images子目录里那样把所有的JavaScript脚本文件集中存放在一个子目录里也将是个好主意。我创建了一个名为scripts的子目录并把showPicjs文件保存到其中。现在需要在图片库HTML文档里插入一个链接来引用这个JavaScript脚本文件。我将把下面这条语句插入那份HTML文档的<head>部分(选择的插入位置是<head>标签之后):有了这条语句把showPic()函数与图片库HTML文档结合起来的任务就已经完成了一半我还需要为HTML文档里的每个图片链接增加一个函数调用动作否则showPic()函数将永远也不会被调用。我将通过增加一个事件处理函数(eventhandler)的办法来完成这项工作。事件处理函数事件处理函数的作用是在预定事件发生时让预先安排好的JavaScript代码开始执行用术语来说就是“触发一个动作”。例如如果想在鼠标指针悬停在某个元素上时触发一个动作就需要使用onmouseover事件处理函数如果想在鼠标指针离开某个元素时触发一个动作就需要使用onmouseout事件处理函数。在“JavaScript美术馆”案例里我想在用户点击某个链接时触发一个动作所以需要使用onclick事件处理函数。我想通过onclick事件处理函数去触发的动作是调用showPic()函数而要想调用这个函数就必须向它传递一个参数:一个带有href属性的元素节点。在图片库HTML文档里当我把onclick事件处理函数嵌入一些链接时我需要把那些链接本身用作showPic()函数的参数。有个非常简单但又非常有效的办法可以做到这一点:使用JavaScript语言中的this关键字。这个关键字的含义是“这个对象”。具体到正在讨论的这个例子我将使用this来表示“这个<a>元素节点”:综上所述我将使用onclick事件处理函数去调用showPic(this)方法。使用事件处理函数调用JavaScript代码的语法如下所示:请注意在如上所示的语法里JavaScript代码是包含在一对引号之间的:我们可以把任意数量的JavaScript语句放在这对引号之间只要把各条语句用分号隔开即可。下面这条语句将完成“使用onclick事件处理函数调用showPic(this)方法”的任务:不过如果只把上面这个事件处理函数插入到HTML文档中的链接里去的话将遇到这样一个问题:在onclick事件发生时不仅showPic(this)函数将被调用链接被点击时的默认行为也将发生。这意味着用户还是会被带到另外一个图片查看窗口里去而这是我不希望发生的事情。我需要阻止这种默认行为的发生。要想达到这一目的我们必须对事件处理函数的工作机制有进一步的了解:在给某个元素添加了事件处理函数后一旦发生预定事件相应的JavaScript代码就会得到执行那些JavaScript代码可以返回一个结果而这个结果将被传递回那个事件处理函数。例如我们可以给某个链接添加一个onclick事件处理函数并让这个处理函数所触发的JavaScript代码返回布尔值true或false。这样一来当这个链接被点击时如果那段JavaScript代码返回给onclick事件处理函数的值是trueonclick事件处理函数将认为“这个链接被点击了”反之如果那段JavaScript代码返回给onclick事件处理函数的值是falseonclick事件处理函数将认为“这个链接没有被点击”。可以通过下面这个简单测试去验证这一结论:当点击这个链接时因为onclick事件处理函数所触发的JavaScript代码返回给它的值是false所以这个链接在被点击时的默认行为将不会发生。同样道理如果像下面这样在onclick事件处理函数所触发的JavaScript代码里增加一条returnfalse语句的话我就可以不让用户被他们所点击的链接带到另外一个图片查看窗口里去:下面是最终完成的onclick事件处理函数在图片库HTML文档里的样子:接下来只要在图片库HTML文档里把这个onclick事件处理函数添加到每个链接上即可。这当然有些麻烦但眼下只能这么做我将在后面的内容里向大家介绍一个可以避免这种麻烦的办法。下面是图片库HTML文档在我以手动方式把这个onclick事件处理函数添加到各个有关链接上之后的样子:现在如果把这个页面加载到Web浏览器里你们将看到一个能够正常工作的“JavaScript美术馆”:在如下所示的页面里不管在图片列表里的哪个链接上点击鼠标都将在这同一个页面里看到相应的图片。对JavaScript函数进行功能扩展在同一个网页上切换显示不同的图片并不是什么新鲜事。有着这类效果的网页和脚本早在WC推出它们的标准化DOM和JavaScript语言之前就已经出现了如今更是得到了广泛的流行。在这种情形下如果你们想让自己与众不同就必须另辟蹊径你们有没有想过在同一个网页上切换显示不同的文本?我可不是在开玩笑利用JavaScript语言和DOM确实可以做到这一点。图片库HTML文档里的每个图片链接都有一个title属性。我想把这个属性的值提取出来并让它们伴随相应的图片一同显示在网页上。title属性的值可以用getAttribute()方法轻而易举地提取出来如果把下面这条语句添加到showPic()函数的开头的话就可以把title属性的值保存到一个变量里:解决了提取title属性值的问题还需要把它插入到HTML文档中的适当位置。为了完成这一工作我需要用到几个新的DOM属性。childNodes属性childNodes属性让我们可以从给定文档的节点树里把任何一个元素的所有子元素检索出来。childNodes属性将返回一个数组这个数组包含给定元素节点的全体子元素:假设我们需要把某个文档的body元素的全体子元素检索出来。首先我们将使用getElementsByTagName()方法来得到body元素。因为每份文档只有一个body元素所以它将是getElementsByTagName("body")方法所返回的数组中的第一个(也是唯一一个)元素:现在变量bodyelement已经指向了那个文档的body元素。接下来可以用如下所示的语法记号把body元素的全体子元素检索出来:写出这个记号显然要比敲入下面这个长长的字符串要简明得多:顺便说一句body元素还有一个更简单的专用记号:现在已经知道如何把body元素的全体子元素检索出来了我们来看看这些信息的用途。首先我们可以精确地查出body元素有多少个子元素。因为childNodes属性返回的是一个数组所以可以用数组数据类型的length属性查出它所包含的元素的个数:请把下面这个小函数添加到showPicjs文件里:这个简单的小函数将弹出一个alert对话框其显示内容是body元素的子元素的总数。我想让这个函数在页面加载时执行而这需要使用onload事件处理函数。把下面这条语句添加到代码段的末尾:这条语句将在页面加载时调用countBodyChildren函数。在Web浏览器里刷新galleryhtml文件。你们将看到一个alert对话框其显示内容是body元素的子元素的总数。那个数字很可能会让你们大吃一惊。nodeType属性根据galleryhtml文件的结构body元素应该只有个子元素:一个h元素、一个ul元素和一个imag元素。可是countBodyChildren()函数给出来的数字却远大于此。之所以会这样是因为文档树的节点类型并非只有元素节点一种。由childNodes属性返回的数组包含着所有类型的节点除了所有的元素节点所有的属性节点和文本节点也包含在其中。事实上文档里几乎每一样东西都是一个节点甚至连空格和换行符都会被解释为节点而它们也全都包含在childNodes属性所返回的数组当中。因此countBodyChildren()函数的返回结果才会是一个相当大的数字。还好我们可以利用nodeType属性来区分文档里的各个节点。这个属性可以让我们知道自己正在与哪一种节点打交道。不过这个属性返回的是一个数字而不是像“element”或“attribute”那样的英文字符串。下面是nodeType属性的调用语法:为了验证这一点请把countBodyChildren()函数中的alter语句替换为下面这条语句这样一来我们就可以知道bodyelement元素的nodeType属性了:在Web浏览器里刷新galleryhtml文件将看到一个显示数字“”的alert对话框。换句话说元素节点的nodeType属性值是。nodeType属性总共有种可取值但其中仅有种具有实用价值:元素节点、属性节点和文本节点的nodeType属性值分别是、和。元素节点的nodeType属性值是。属性节点的nodeType属性值是。文本节点的nodeType属性值是。这个意味着可以让我们的函数只对某种特定类型的节点进行处理。例如完全可以编写出一个只对元素节点进行处理的函数。在HTML文档里增加一段描述性文本为了让我的“JavaScript美术馆”变得与众不同我决定给它增加一个文本节点。我想在显示图片时把这个文本节点的值替换为一个来自某个属性节点(某个图片链接的title属性)的值。首先需要为打算显示的文本安排显示位置。我将在galleryhtml文件里增加一个新的文本段。我决定把它安排在<img>标签之前。我将为它设置一个独一无二的id值这样就能在JavaScript函数里方便地引用它了:上面这条语句将把<p>元素的id属性设置为description(描述)这个单词可以让这个元素的用途一目了然。如下所示包含在此元素里的文本现在是“Chooseanimage”但我打算在切换显示图片时把这段文本同时替换为相应的描述性文字。我想达到的预期效果是:在“JavaScript美术馆”里的某个图片链接被点击时不仅要把“占位符”图片替换为那个链接的href属性所指向的图片还要把这段文本同时替换为那个链接的title属性值。为了实现这一想法需要对showPic()函数做一些改进。用JavaScript代码改变<p>元素的文本内容为了把“JavaScript美术馆”里的图片说明在某个图片链接被点击时动态地替换为那个链接的title属性值我需要对showPic()函数做一些修改。下面是showPic()函数现在的样子:首先我需要在showPic()函数里增加一些语句来提取whichpic对象的title属性值。我将把提取到的title属性值存入text变量。这些事可以轻而易举地利用getAttribute()方法完成:接下来为了让自己能在代码里方便地引用那段id属性值等于description的文本我决定创建一个新的变量来存放它:下面是showPic()函数在我给它增加了上述两个变量之后的样子:我们的下一个任务是实现文本的切换显示效果。nodeValue属性如果想改变某个文本节点的值那就使用DOM提供的nodeValue属性它的用途正是检索(和设置)节点的值:但这里有个大家必须注意的细节:在用nodeValue属性检索description对象的值时你得到的并不是包含在这个段落里的文本。可以用下面这条alert语句来验证这一点:这个调用将返回一个值。<p>元素的nodeValue属性值是一个空值而我们这里需要的是<p>元素所包含的文本的值。包含在<p>元素里的文本是另一种节点它在DOM里是<p>元素的第一个子节点。换句话说如果想获得<p>元素的文本内容就必须检索它的第一个子节点的nodeValue属性值。下面这条alert语句可以找到我们想要的内容:这个调用的返回值才是我们正在寻找的“Chooseanimage”。这个值来自childNodes数组的第一个(下标是)元素。firstChild和lastChild属性数组元素childNodes有个更直观易读的同义词。无论何时何地只要需要访问childNodes数组的第一个元素我们都可以把它写成firstChild这个记号本身是一个属性:这种用法与下面这个语法记号完全等价:单词“firstChild”不仅更加简短还更加具有可读性。DOM还提供了一个与之对应的lastChild属性:这个语法记号代表着childNodes数组的最后一个元素。如果不想通过lastChild属性去访问这个节点我们将不得不使用如下所示的语法记号:与简明易懂的lastChild相比这么复杂的语法记号恐怕没人会喜欢。利用nodeValue属性刷新<p>元素的文本内容现在我们将回到showPic()函数。我将对id属性值等于description的<p>元素所包含的文本节点的nodeValue属性进行刷新。具体到这个id属性值等于description的<p>元素因为它只有一个子节点所以选用firstChild属性或是选用lastChild属性的效果是完全一样的。既然如此我决定选用firstChild属性。我可以把节里的alter语句改写为如下所示的样子:两条语句的效果完全一样(都将显示“Chooseanimage”消息)但这里的代码显然更容易阅读和理解。nodeValue属性的用途并非仅限于此。我们不仅可以用它来检索某个节点的值还可以用它来设置某个节点的值后一种用法正是我目前最需要的。还记得刚才在showPic()函数里的text变量吗?当“JavaScript美术馆”页面上的某个图片链接被点击时showPic()函数会把这个链接的title属性值传递给text变量。而我现在将用text变量去刷新id值等于description的那个<p>元素的第一个子节点的nodeValue属性值如下所示:下面是我为了改进showPic()函数而给它添加的三条新语句:如果用日常生活中的语言来说这三条语句的含义依次是:当“JavaScript美术馆”页面上的某个图片链接被点击时这个链接的title属性值将被提取并保存到text变量中。找到那个id="description"的<p>元素并把这个对象保存到变量description里去。把description对象的第一个子节点的nodeValue属性值设置为变量text的值。下面是完成上述改进后的showPic()函数的代码清单:如果想测试一下这些扩展功能请把改进后的showPic()函数存入showPicjs文件然后在浏览器里刷新galleryhtml文档。现在点击这个网页上的某个图片链接时你们将看到两种效果:“占位符”图片将被替换为这个链接所指向的一张新图片同时图片下方的描述性文字也将被替换为这个链接的title属性值如下所示。你们可以在http:friendsofedcom网站上找到“JavaScript美术馆”脚本文件和HTML文档。我在示例中用到的图片也可以在那里找到但我建议大家找一些自己的图片来测试这个脚本那样会更有意思。如果想让这个“JavaScript美术馆”变得更美观可以再给它增加一个像下面这样的样式表:请把这些CSS代码存入layoutcss文件并把这个文件存放到styles子目录里。然后就可以在galleryhtml文档的<head>部分用一个<link>标签来引用这个文件了如下所示:下面是“JavaScript美术馆”在经过上面那个简单的样式表修饰之后的显示效果。小结本章向大家介绍了一个简单的JavaScript应用案例。在实现这个案例的过程中我们还向大家介绍了DOM提供的几个新属性它们是:childNodesnodeTypenodeValuefirstChildlastChild本章的学习重点有两个:一是如何利用DOM所提供的方法去编写图片库脚本二是如何利用事件处理函数把JavaScript代码与网页集成在一起。从表面上看我们的“JavaScript美术馆”已经大获成功但它实际上还有许多地方值得改进而那将是随后两章里的讨论重点。在下一章中我将向大家介绍一些JavaScript脚本编程方面的原则和良好习惯我希望它们能让你们领悟这样一个道理:通往终点的过程与终点本身同样重要。在那之后我将向你们演示如何把那些编程原则和良好习惯应用到“JavaScript美术馆”案例上。

用户评论(0)

0/200

精彩专题

上传我的资料

每篇奖励 +2积分

资料评价:

/39
1下载券 下载 加入VIP, 送下载券

意见
反馈

立即扫码关注

爱问共享资料微信公众号

返回
顶部