JavaScript学习笔记--07

来源:互联网 发布:c语言 a算法代码 编辑:程序博客网 时间:2024/05/29 13:23

案例研究:JavaScript美术馆的改进版

前面学习了JavaScript的编程原则和良好习惯,这节利用前面所学的编程原则和良好习惯,对JavaScript美术馆进行改进。

解决“预留退路”问题

第一个问题是:如果JavaScript功能被禁用,会怎么样?

仔细检查之前写的showPic()函数的代码后,可以知道之前的脚本已经为次预留了退路:即使JavaScript功能被禁用,用户也可以毫无问题地浏览到JavaScript美术馆里的所有图片,网页里的所有链接也都可以正常的工作:

<li>        <a href="images/巴西野牡丹.jpg" onclick="showPic(this); return false;" title="baxiyebaihe">巴西野百合</a>  </li>
在没有JavaScript“干扰”的情况下,浏览器经验者href属性给出的链接前进,用户将看到一张新图片而不是“该网页无法显示”之类的出错信息。虽说这与JavaScript在当前网页切换显示新图片的效果要略差一些,但网页的基本功能并为受到损害——页面上的所欲内容都可以访问。

说明,前面写的JavaScript美术馆通过了第一个测试。

解决“分离JavaScript”问题

下一个问题是与在HTML文档里调用JavaScript代码的具体做法有关,它是这样的:HTML文档的结构与JavaScript代码所实现的行为分开了吗?简而言之,就是网页的行为层(JavaScript)与其结构(XHTML)是彼此互不干扰、还是两种代码混杂在一起?
而之前写的JavaScript美术馆的案例,显然是“它们混杂在一起了”,因为当初把onclick事件处理函数直接插入到了HTML文档里,这显然不符合“分离JavaScript原则”。应该要在外部文件里完成添加onclick事件处理函数的工作,那样才能让HTML文档没有“杂质”,就像这样:
<li>        <a href="images/巴西野牡丹.jpg" " title="baxiyebaihe">巴西野百合</a>  </li>

把JavaScript分离出来,必须找到一种“挂钩”把JavaScript代码与HTML文档中的有关标记关联起来。有很多方法可以实现这一目的。

更为方便简单的是,我们观察到图片清单里的各个链接有一个共同点:他们都包含在同一个列表清单元素(ul)里。给整个图片清单设置一个独一无二的ID的办法要简单得多:

<ul id="imagegallery">    <li>        <a href="images/巴西野牡丹.jpg" onclick="showPic(this); return false;" title="baxiyebaihe">巴西野百合</a>    </li>    <li>        <a href="images/白玫瑰.jpg" onclick="showPic(this); return false;" title="baimeigui">白玫瑰</a>    </li>    <li>        <a href="images/白玫瑰裙.jpg" onclick="showPic(this); return false;"  title="baimeiguiqun">白玫瑰裙</a>    </li>    <li>        <a href="images/sunflower.jpg" onclick="showPic(this); return false;"  title="xiangrikui">向日葵</a>    </li></ul>
添加事件处理函数、进行必要检查、创建必要变量
现在,需要编写一个简短的函数把有关操作关联到onclick事件上,将其命名为prepareGallery。

下面是这个函数应该要完成的工作:

  • 检查当前浏览器是否理解getElementsByTagName()方法
  • 检查当前浏览器是否理解getElementById()方法
  • 检查当前网页是否包含着一个id属性是“imagegallery”的元素
  • 构造一个循环来对“imagegallery”元素中的链接进行遍历处理
  • 对onclick事件处理函数进行设置,让它在有关链接被点击时弯沉改一下操作:1.把这个链接作为参数传递给showPic()函数;2.取消链接被点击时的默认行为,不让浏览器打开这个勘界。
prepareGallery()函数不需要参数,所以这个函数后面的圆括号里面用不着些任何东西。

结构化程序设计(structed programming)理论有一条原则:每个函数应该只有一个入口点和一个出口点。

但是,同一个函数有多个出口点的情况是可以接受的,但前提是它们应该集中出现在这个函数的开头部分。

目前为止的prepareGallery()函数:

function prepareGallery(){    if (!document.getElementsByTagName) return false;    if(!document.getElementById)   return false;    if(!document.getElementById("imagegallery"))   return false;    var gallery=document.getElementById("imagegallery");    var links=gallery.getElementsByTagName("a");}
创建循环
for(var i=0;i<links.length;i++){}
完成必要的操作

links[i].onclick=function(){}
这条语句定义了一个匿名函数。这是一种”临时抱佛脚”式的函数创建办法,最适合用来定义在整个脚本里只出现了一次的函数:匿名函数没有名字,只能在哪里定义、在哪里使用。

完成JavaScript函数

function prepareGallery(){    if (!document.getElementsByTagName) return false;    if(!document.getElementById)   return false;    if(!document.getElementById("imagegallery"))   return false;    var gallery=document.getElementById("imagegallery");    var links=gallery.getElementsByTagName("a");    <strong>for(var i=0;i<links.length;i++){        links[i].onclick=function(){            showPic(this);            return false;        }    }</strong>}
调用此函数时,它将把onclick事件绑定到id属性值等于“imagegallery”的那个元素所包含的各个链接上去。

把多个JavaScript函数绑定到onload事件处理函数上

必须执行prepareGallery()函数才能对onclick事件进行绑定。

如果现在就执行这个函数,它将无法完成其工作:在HTML文档完成加载之前,DOM是不完整的。必须让这个函数只在网页加载完毕之后才得到执行。网页加载完毕时会出发一个Onload事件,这个事件与window对象相关联。为了让事态的发展不偏离计划,必须把prepareGallery()函数绑定到这个事件上:

window.onload=prepareGallery;
这条浅显易懂的语句解决了上面的问题,但是考虑还不长远。如果有两个函数:firestFunction()和secondFunction()。想让他们两都在页面加载时得到执行,该如何解决?如果把它们一一绑定到onload事件上,它们中将只有最后那个才会被实际执行:

window.onload=firstFunction;window.onload=secondFunction;
secondFunction将取代firestFunction。由此可以得出一个结论:每个事件处理函数只能绑定一条指令。

还有有个小技巧可以绕过这一难题:可以先创建一个匿名函数来容纳这两个函数,然后把那个匿名函数绑定到onload事件上,如下所示:

window.onload=function(){firstFunction();secondFunction();}
这个技巧既简单又实用——在需要绑定的函数不是很多的场合,这应该是最简明的解决方案了。

还有一个更通用的解决方案——不管要在页面加载完毕时执行多少个函数,它都可以应付自如。需要额外写一个函数,这个函数的名字是addLoadEvent(),它只有一个参数:打算在页面加载完毕时执行的函数的名字。

下面是addLoadEvent()函数将要完成的操作:

  • 把现有的window.onload事件处理函数的值存入变量onload。
  • 如果在这个处理函数上还没有绑定任何函数,就像平时那样把新函数添加给它。
  • 如果在这个处理函数上已经绑定了一些函数,把新函数追加到现有的指令的末尾。
addLoadEvent()函数的代码清单:

function addLoadEvent(){    var oldonload=window.onload;    if(typeof window.onload!='function'){       window.onload=func;    }else{        window.onload=function(){            oldonload();            func();        }    }}
这相当于把那些将在页面加载完毕时执行的函数创建为一个队列。如果想把刚才那两个函数添加到这个队列里去,只需写如下的代码就行了:

addLoadEvent(firstFunction);addLoadEvent(secondFunction);
这个函数非常有用,尤其是在代码变得越来越复杂的时候。无论打算在页面加载完毕时执行多少个函数,都只要多写一条语句就可以安排好一切。

JavaScript函数的优化:不要做太多的假设

showPic()函数没有进行任何测试和检查。showPic()函数中用到了id属性值等于placeholder和description的元素,但却没有做任何的检查:

慎用onkeypress事件处理函数

这里决定不添加onkeypress事件处理函数。这个事件处理函数很容易引起问题。用户每按下键盘上的一个按键都会触发它。在某些浏览器里,那甚至包括Tab键!这意味着如果绑定在onkeypress事件处理函数上的某个函数的返回值是false,那些使用键盘来进行浏览的用户就无法离开当前连接。这里的“JavaScript美术馆”网页就存在着这样的问题——只要图片切换成功,showPic()函数就将返回false。实际上,onclick事件处理函数比想象中要聪明,尽管它的名字“onclick”给人以一种它只与鼠标点击动作相关联的印象,但事实并非如此:在几乎所有的浏览器里,用TAB键移动到某个链接然后按下回车键的动作也会触发onclick事件。从这一点来看,把它命名为“onactive”也许更恰如其分。

PS:如果没有特殊理由,最好不要使用onkeypress事件处理函数。

JavaScriptCSS结合起来

HTML文档里为JavaScript代码留下了一个“挂钩”:

<ul id="imagegallery">

这个挂钩完全可以用在CSS样式表里。



0 0