《DOM Scripting》学习笔记-——第五章、第六章 案列改进
第四章的案例代码可以得到更好的改进。例如:预留退路、向后兼容性和分离js。
原html代码:
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Document</title> 6 </head> 7 <body> 8 <h1>Snapshots</h1> 9 <ul> 10 <li> 11 <a href="images/rose.jpg" onclick="showPic(this);return false" title="A fireworks display">Fireworks</a> 12 </li> 13 <li> 14 <a href="images/rose.jpg" onclick="showPic(this);return false" title="A cup of black coffee"> 15 Coffee</a> 16 </li> 17 <li> 18 <a href="images/rose.jpg" onclick="showPic(this);return false" title="A red, red rose">Rose</a> 19 </li> 20 <li> 21 <a href="images/bigben.jpg" onclick="showPic(this);return false" title="The famous clock"> 22 Big Ben</a> 23 </li> 24 </ul> 25 26 <img id="placeholder" src="images/placeholder.gif" alt="my image gallery" /> 27 <p id="description">Choose an image.</p> 28 29 </body> 30 </html>
原js代码:
1 function showPic(whichpic) { 2 var source = whichpic.getAttribute("href"); 3 var placeholder = document.getElementById("placeholder"); 4 placeholder.setAttribute("src",source); 5 var text = whichpic.getAttribute("title"); 6 var description = document.getElementById("description"); 7 description.firstChild.nodeValue = text; 8 }
一、解决预留退路问题:
没有使用js伪协议,即使js功能被禁用,a链接仍可以链接到图片,虽然与js在当前页面上切换显示新图片的效果略差一些,但网页的基本功能没有受到损害,页面上的所有内容都可以访问。
二、解决分离js的问题:
1、onclick事件处理函数直接插到html文档里,不符合“分离js”原则。
解决:
(1)找到“挂钩”把js代码与html文档中有关标记关联起来。
a、给每个链接添加一个class属性。(较麻烦)
b、给ul加一个id(id=“imagegallery”)
(2)添加事件处理函数,该函数需要具有以下功能:
a、检查当前浏览器是否理解getElementsByTagName()方法。
b、检查当前浏览器是否理解getElementById()方法。
c、检查当前网页是否包含着一个id属性值是“imagegallery”的元素。
d、构造一个循环来对“Imagegallery”元素中的链接进行遍历处理。
e、对onclick事件处理函数进行设置,让它在有关链接被点击时完成以下操作:把这个链接作为参数传递给showpic()函数;取消链接被点击时的默认行为,不让浏览器打开这个链接。
①进行必要的检查
1 if (!document.getElementsByTagName) { 2 return false; 3 } 4 if (!document.getElementById) { 5 return false; 6 }
或
1 function prepareGallery() { 2 if (!document.getElementsByTagName) return false; 3 if (!document.getElementById) return false; 4 if (!document.getElementById("imagegallery")) return false;
结构化程序设计(structed programming)原则:每个函数应该只有一个入口点和一个出口点。
但是过分拘泥以上原则会使得代码难以阅读。所以一般而言,同一个函数有多个出口点的情况是可以接受的,但前提是它们应该集中出现在函数的开头部分。如第二种方法所示。
②创建必要的变量
1 var gallery = document.getElementById("imagegallery"); 2 var links = gallery.getElementsByTagName("a");
③创建循环
for ( var i=0; i < links.length; i++) {
④完成必要的操作
1 links[i].onclick = function() { 2 showPic(this); 3 return false; 4 }
匿名函数一般用于只出现一次的函数
1 function prepareGallery() { 2 if (!document.getElementsByTagName) return false; 3 if (!document.getElementById) return false; 4 if (!document.getElementById("imagegallery")) return false; 5 var gallery = document.getElementById("imagegallery"); 6 var links = gallery.getElementsByTagName("a"); 7 for ( var i=0; i < links.length; i++) { 8 links[i].onclick = function() { 9 showPic(this); 10 return false; 11 } 12 } 13 }
⑥把多个js函数绑定到onload事件处理函数上。在html文档完成加载之前,DOM是不完整的,必须使这个函数只在网页加载完毕之后才得到执行。网页加载完毕时会触发一个onload事件,这个事件与window对象相关联。
1 window.onload = function() { 2 firstFunction(); 3 secondFunction(); 4 }
或者使用addLoadEvent()函数
1 function addLoadEvent(func) { 2 var oldonload = window.onload; 3 if (typeof window.onload != 'function') { 4 window.onload = func; 5 } else { 6 window.onload = function() { 7 oldonload(); 8 func(); 9 } 10 } 11 }
addLoadEvent(firstFunction);
addLoadEvent(secondFunction);
三、js函数的优化
1、不要做太多假设
showPic()函数没有进行任何测试和检查。虽然showPic()函数由prepareGallery()函数调用,在prepareGallery()函数的开头对getElementById()和getElementsByTagName()等DOM方法是否存在进行过检查,但是在showPic()函数中仍存在太多假设,比如对于id属性值等于placeholder和description的元素,函数并未对这些元素进行检查。
1 function showPic(whichpic) { 2 if (!document.getElementById("placeholder")) return true;//如果不存在placeholder,图片切换不成功,则返回true,通过a链接点击到图片 3 var source = whichpic.getAttribute("href"); 4 var placeholder = document.getElementById("placeholder"); 5 placeholder.setAttribute("src",source); 6 if (!document.getElementById("description")) return false;//已经读到此说明之前图片切换成功,所以要返回false,使a链接不能使用。 7 var text = whichpic.getAttribute("title"); 8 var description = document.getElementById("description"); 9 description.firstChild.nodeValue = text; 10 return false;//已经读到此说明之前图片切换成功,所以要返回false,使a链接不能使用。 11 }
此时prepareGallery()函数的代码:
1 function prepareGallery() { 2 if (!document.getElementsByTagName) return false; 3 if (!document.getElementById) return false; 4 if (!document.getElementById("imagegallery")) return false; 5 var gallery = document.getElementById("imagegallery"); 6 var links = gallery.getElementsByTagName("a"); 7 for ( var i=0; i < links.length; i++) { 8 links[i].onclick = function() { 9 return showPic(this); 10 } 11 } 12 }