← 返回目录

目录

第 7 / 7 卷作者:hwl1日期:

图 12-1
图 12-1

C o n t e n t s目录

推荐序

赞誉

前言

致谢

第 1 章从网站重构说起/1

1.1糟糕的页面实现,头疼的维护工作/2

1.2Web 标准—结构、样式和行为的分离/4

1.3前端的现状/6

1.4打造高品质的前端代码,提高代码的可维护性—精简、重用、有序/8
第 2 章团队合作/9
2.1揭秘前端开发工程师/10
2.2欲精一行,必先通十行/13
2.3增加代码可读性—注释/15
2.4提高重用性—公共组件和私有组件的维护/15
2.5冗余和精简的矛盾—选择集中还是选择分散/16
2.6磨刀不误砍柴工—前期的构思很重要/17

2.7制订规范/18

2.8团队合作的最大难度不是技术,是人/18

第 3 章高质量的 HTML/19

3.1标签的语义/20

3.2为什么要使用语义化标签/21

3.3如何确定你的标签是否语义良好/26

3.4常见模块你真的很了解吗/36

3.4.1标题和内容/36

3.4.2表单/38

3.4.3表格/40

3.4.4语义化标签应注意的一些其他问题/43

第 4 章高质量的 CSS/44

4.1怪异模式和 DTD/45

4.2如何组织 CSS/46

4.3推荐的 base.css/49

4.4模块化CSS—在CSS中引入面向对象编程思想/55
4.4.1 如何划分模块—单一职责/55
4.4.2 CSS的命名—命名空间的概念/60
4.4.3 挂多个class还是新建class—多用组合,少用继承/66
4.4.4 如何处理上下margin/72
4.5低权重原则—避免滥用子选择器/81
4.6CSS sprite/85
4.7CSS的常见问题/88
4.7.1 CSS的编码风格/88

4.7.2id 和 class/89

4.7.3CSS hack/89

4.7.4解决超链接访问后hover样式不出现的问题/93
4.7.5hasLayout/94
4.7.6块级元素和行内元素的区别/95
4.7.7display:inline-block和hasLayout/97
4.7.8relative、absolute和float/103
4.7.9居中/104
4.7.10网格布局/112
4.7.11z-index的相关问题以及Flash和IE 6下的select元素/122
4.7.12插入png图片/129
4.7.13多版本IE并存方案—CSS的调试利器IETester/131

第 5 章高质量的 JavaScript/133

5.1养成良好的编程习惯/134

5.1.1团队合作—如何避免 JS 冲突/134

5.1.2给程序一个统一的入口—window.onload和DOMReady/148
5.1.3CSS放在页头,JavaScript放在页尾/159
5.1.4引入编译的概念—文件压缩/160
5.2 JavaScript的分层概念和JavaScript库/162
5.2.1JavaScript如何分层/162
5.2.2base层/163
5.2.3common层/181
5.2.4page层/184
5.2.5JavaScript库/185
5.3 编程实用技巧/187
5.3.1弹性/187

5.3.2getElementById、getElementsByTagName 和 getElements-

ByClassName/193

5.3.3可复用性/196

5.3.4避免产生副作用/199

5.3.5通过传参实现定制/203

5.3.6控制 this 关键字的指向/207

5.3.7预留回调接口/211

5.3.8编程中的 DRY 规则/212

5.3.9用 hash 对象传参/215

5.4面向对象编程/217

5.4.1面向过程编程和面向对象编程/217

5.4.2JavaScript 的面向对象编程/224

5.4.3用面向对象方式重写代码/245

5.5其他问题/251

5.5.1prototype 和内置类/251

5.5.2标签的自定义属性/255

5.5.3标签的内联事件和 event 对象/260

5.5.4利用事件冒泡机制/263

5.5.5改变 DOM 样式的三种方式/267

附录 A写在规则前面的话/271

附录 B命名规则/272

附录 C分工安排/274

附录 D注释规则/276

附录 EHTML 规范/278

附录 FCSS 规范/280

附录 GJavaScript 规范/282

第 1 章从网站重构说起

本章内容

糟糕的页面实现,头疼的维护工作

Web 标准——结构、样式和行为的分离

前端的现状

打造高品质的前端代码,提前代码的可维护性——精简、重用、有序

1.1 糟糕的页面实现,头疼的维护工作

代码清单 1-1 一个糟糕老网页的实现

<html> <head>

<meta http-equiv="Content-Type" content="text/html; charset=gb2312"> <style type=text/css>

td,body {font-size: 15px; font-family:arial,sans-serif,宋体;} body{margin-top:0px;margin-left:0px;margin-right:0px;background-color: #fcfff7}

a:link{ color:#000000; text-decoration:none;padding-left:4px; } a:visited{COLOR: #000000; TEXT-DECORATION: none;padding-left:4px;}

a:active{color:green;text-decoration:none;padding-left:4px;}a:hover{color:red;textdecoration:underline;padding-left:4px;}

a.m:link{ color:#000000; text-decoration:none;padding-left:0px;} a.m:visited{COLOR: #000000; TEXT-DECORATION: none;padding-left:0px;}

a.m:active{color:green;text-decoration:none;padding-left:0px;} a.m:hover{color:red;text-decoration:underline;padding-left:0px;}

.t1{border-width:1px 1px 1px 1px;border-style:solid;font-size:12px;text-align:

center} .bgg{border-color:#8AB78A; width:779px}

.f9pt{font-size: 12px;} #sfont a,#sfont b{font-size:13px;}

</style> <base target="_blank">

<title>网址之家--动漫</title> <script src="js/usertrack.js"></script>

</head> <body>

<div align="center"><center> <table border="0" cellpadding="0" cellspacing="0" width="778" height="51">

<tr> <td width="230" height="51"><a href="http://www.xxx.com" target="_self"

class="m"><img src="logo.gif" alt="xxx.com" width="168" height="63"

border="0"></a></td> <td height="51" align="center"><table width="100%" border=0cellpadding=0

cellspacing=0> <form name=form1 action=http://www.baidu.com/s>

<input type=hidden name=tn value=abc> <tr>

<td colspan="2" id=sfont>

<b>网页</b>

</tr> <tr>

<td height="30" valign="top"> <input type=text name=wd size=40 onMouseOver=this.focus()

onFocus=this.select() style="margin-bottom:-5px;

font-size:16px;height:1.78em;font-family:arial,sans-serif,宋体;padding-top:2px;

padding-left:1px" maxlength=100> <input type=submit style="height:1.82em;width:6.4em;font-size:16px;

margin-bottom:-5px; padding-top:2px" value="百度一下"> </td>

<td width="80" valign="top" class="f9pt"> </td> </tr>

</form></table></td> </tr>

</table> </center></div>

<script language=javascript> <!--

UserTrack.init(1,"动漫")

document.form1.wd.focus()

//--> </script>

</body> </html>

1.2 Web 标准——结构、样式和行为的分离

代码清单 1-2 结构、样式和行为混杂的网页

<td width="100%" height="20"class="f9pt"align="center"> <font color="#346F0E">下载</font>

<input type=text name=wd size=40 onMouseOver=this.focus()

onFocus=this.select() style="margin-bottom:-5px;

font-size:16px;height:1.78em;font-family:arial,sans-serif,宋体;padding-top:2px;

padding-left:1px" maxlength=100> </td>

代码清单 1-3结构、样式和行为分别用单独文件分离开

test.html 文件:

<link rel=”stylesheet” type=”text/css” href=”test.css” /> <td class="f9pt myTd">

<span class=”myFont”>下载</span> <input type=”text” name=”wd” size=”40” id=”myInput” maxlength=”100” />

</td> <script type=”text/Javascript” src=”test.js”></script>

==============================================================

test.css 文件:

.myTd{width:100%;height:20px;text-align:center;} .myFont{color:#346F0E;}

#myInput{margin-bottom:-5px;font-size:16px;height:1.78em;font-family:arial,sansserif,宋体;padding-top:2px;padding-left:1px}

==============================================================

myInput.onmouseover = function(){ this.focus();

} myInput.onfocus = function(){

this.select();

}

代码清单 1-4 样式和行为在网页内分离开

<style type=”text/CSS”> .myTd{width:100%;height:20px;text-align:center;}

.myFont{color:#346F0E;} #myInput{margin-bottom:-5px;font-size:16px;height:1.78em;font-family:arial,sans-

serif,宋体;padding-top:2px;padding-left:1px} </style>

<td class="f9pt myTd"><span class=”myFont”>下载</span><input type=”text” name=”wd”

size=”40” id=”myInput” maxlength=”100” /></td> <script type=”text/Javascript”>

var myInput = document.getElementById(“myInput”);

myInput.onmouseover = function(){ this.focus();

} myInput.onfocus = function(){

this.select();

} </script>

1.3 前端的现状

1.4 打造高品质的前端代码,提高代码的可维护性——精简、重

用、有序

第 2 章团队合作

本章内容

揭密前端开发工程师

欲精一行,必选通十行

增加代码可读性——注释

提高重用性——公共组件和私有组件的维护

冗余和精简的矛盾——选择集中还是选择分散

磨刀不误砍柴功——前期的构思很重要

制订规范

团队合作最大的难度不是技术,是人

2.1 揭密前端开发工程师

2.2 欲精一行,必先通十行

2.3 增加代码可读性——注释

2.4 提高重用性——公共组件和私有组件的维护

2.5 冗余和精简的矛盾——选择集中还是选择分散

2.6 磨刀不误砍柴功——前期的构思很重要

2.7 制订规范

2.8 团队合作最大的难度不是技术,是人

第 3 章高品质的 HTML

本章内容

标签的语义

为什么要使用语义化标签

如何确定你的标签是否语义良好

常见模块详解

3.1 标签的语义

3.2 为什么要使用语义化标签

代码清单 3-1 简单页面

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"

"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml">

<head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

<title>阿当的简单示例</title> </head>

<body> <h1>h1 标签</h1>

<h2>h2 标签</h2> <h3>h3 标签</h3>

<p>p 标签</p> <div>div 标签</div>

<span>span 标签</span> <strong>strong 标签</strong>

<input type="text" value="input 标签" /> <textarea>textarea 标签</textarea>

<input type="button"value="提交" /> <ul>

<li>1</li> <li>2</li>

<li>3</li> <li>4</li>

<li>5</li> <li>6</li>

<li>7</li> <li>8</li>

</ul> </body>

</html>

代码清单 3-2 简单页面的 CSS 代码

h1{font-size:12px;font-weight:normal;} h2{font-size:16px;}

h3{font-size:20px;font-weight:normal;}

div{display:inline;} strong{display:block;padding:10px;border:1px dashed #000;margin:20px 50px;}

.text{width:300px;height:100px;} textarea{width:150px;height:20px;border:4px solid

#999;background:#ccc;overflow:auto;} .btn{border:3px solid green;background:black;color:#fff;}

ul{list-style:none;} li{padding:10px;border:1px dashed #ccc;float:left;margin:0 2px;}

3.3 如何确定你的标签是否语义良好

3.4 常见模块详解

3.4.1 标题和内容

代码清单 3-3标题和内容模块实现方案一

html 部分:

<div class=“h2”>标签的语义<a href=“#”>更多&gt;&gt;</a></div> <div class=“p”>段落一的内容。。。<span class=“strong”>根据浏览器的默认样式 </span>。。。</div>

<div class=“p”>段落二的内容</div>

CSS 部分:

.h2{position:relative;border-bottom:1px dashed #fff;} .h2 a{position:absolute;right:0;top:0;}

.p{text-indent:2em;line-height:150%;margin:0 0 20px 0;} .strong{color:red;}

代码清单 3-4标题和内容模块实现方案一的语义

<分隔 class=“h2”>标签的语义<锚点 href=“#”>更多&gt;&gt;</锚点></分隔> <分隔>段落一的内容。。。<范围 class=“strong”>根据浏览器的默认样式 </范围>。。。</分隔>

<分隔>段落二的内容</分隔>

代码清单 3-5标题和内容模块实现方案二

html 部分:

<h2>标签的语义 <a href=“#”>更多&gt;&gt;</a> </h2> <p>段落一的内容。。。<strong>根据浏览器的默认样式 </strong>。。。</p>

<p>段落二的内容</p>

CSS 部分:

h2{position:relative;border-bottom:1px dashed #fff;} h2 a{position:absolute;right:0;top:0;}

p{text-indent:2em;line-height:150%;margin:0 0 20px 0;} strong{color:red;font-weight:normal}

代码清单 3-6标题和内容模块实现方案二的语义

<二级标题>标签的语义<锚点 href=“#”>更多&gt;&gt;</锚点> </二级标题> <段落>段落一的内容。。。<强调>根据浏览器的默认样式 </强调>。。。</段落>

<段落>段落二的内容</段落>

代码清单 3-7标题和内容模块实现方案三

html 部分:

<h2>标签的语义</h2>

CSS 部分:

h2{} a{}

p{text-indent:2em;line-height:150%;margin:0 0 20px 0;} strong{color:red;font-weight:normal}

代码清单 3-8标题和内容模块实现方案三的语义

<二级标题>标签的语义</二级标题> <锚点 href=“#”>更多&gt;&gt;</锚点>

<段落>段落一的内容。。。<强调>根据浏览器的默认样式 </强调>。。。</段落> <段落>段落二的内容</段落>

代码清单 3-9标题和内容模块实现方案三的改进版

html 部分:

<div class=“title”> <h2>标签的语义</h2>

<a href=“#”>更多&gt;&gt;</a> </div>

<p>段落一的内容。。。<strong>根据浏览器的默认样式 </strong>。。。</p> <p>段落二的内容</p>

CSS 部分:

.title{border-bottom:1px dashed #fff;text-align:right;} .title h2{float:left;}

p{text-indent:2em;line-height:150%;margin:0 0 20px 0;} strong{color:red;font-weight:normal}

3.4.2 表单

代码清单 3-10表单模块实现方案一

<form action="" method="" class="fieldset"> <div><span>帐号:</span> <input type="text" id="name" /></div>

<div><span>密码:</span> <input type="password" id="pw" /></div> <input type="submit" value="登陆" class="subBtn" />

</form>

代码清单 3-11表单模块实现方案一的语义

<表单 action=“” method=“” class=“fieldset”> <分隔><范围>帐号:</范围> <表单项 type="text" id="name" /></分隔>

<分隔><范围>密码:</范围> <表单项 type=“password” id=“pw” /></分隔> <表单项 type="submit" value="登陆" class="subBtn" />

</表单>

代码清单 3-12表单模块实现方案二

<form action="" method=""> <fieldset>

<legend>登录表单</legend> <p><label for="name">帐号:</label> <input type="text" id="name"

/></p> <p><label for="pw">密码:</label> <input type="password" id="pw"

/></p> <input type="submit" value="登陆" class="subBtn" />

</fieldset> </form>

<域集名>登录表单</域集名> <段落><表单项说明 for=“name”>帐号:</表单项说明> <表单项 type=“text” id=

“name” /></段落> <段落><表单项说明 for=“pw”>密码:</表单项说明 > <表单项 type=“password” id=

“pw” /></段落> <表单项 type="submit" value="登陆" class="subBtn" />

</域集> </表单>

代码清单 3-14表格模块实现方案一

<div class="caption">几种页面实现的比较</div> <table border="1">

<tr class="thead"><td class="th">实现方式</td><td class="th">代码量</td><td class="th">搜索引擎友好</td><td class="th">特殊终端兼容</td></tr>

<tr><td class="th">table 布局</td><td>多</td><td>差</td><td>一般</td></tr> <tr><td class="th">乱用标签的 CSS 布局</td><td>少</td><td>一般</td><td>差

</td></tr> <tr><td class="th">标签语义良好的 CSS 布局</td><td>少</td><td>好</td><td>好

</td></tr> </table>

代码清单 3-15表格模块实现方案一的语义

<分隔 class=“caption”>几种页面实现的比较</分隔> <表格 border="1">

<表格行 class="thead"><表格单元格 class="th">实现方式</表格单元格><表格单元格 class="th">代码量</表格单元格><表格单元格 class="th">搜索引擎友好</表格单元格><表格单元格

class="th">特殊终端兼容</表格单元格></表格行> <表格行><表格单元格 class="th">table 布局</表格单元格><表格单元格>多</表格单元格><表

格单元格>差</表格单元格><表格单元格>一般</表格单元格></表格行> <表格行><表格单元格class="th">乱用标签的CSS布局</表格单元格><表格单元格>少</表格单元

格><表格单元格>一般</表格单元格><表格单元格>差</表格单元格></表格行> <表格行><表格单元格class="th">标签语义良好的CSS布局</td><表格单元格>少</表格单元格><

表格单元格>好</表格单元格><表格单元格>好</表格单元格></表格行> </表格>

<分隔><范围>帐号:</范围> <表单项 type="text" id="name" /></分隔> <分隔><范围>密码:</范围> <表单项 type=“password” id=“pw” /></分隔>

<表单项 type="submit" value="登陆" class="subBtn" /> </表单>

代码清单 3-16表格模块实现方案二

<table border="1"> <caption>几种页面实现的比较</caption>

<thead> <tr><th>实现方式</th><th>代码量</th><th>搜索引擎友好</th><th>特殊终端兼容

</th></tr> </thead>

<tbody> <tr><th>table 布局</th><td>多</td><td>差</td><td>一般</td></tr>

<tr><th>乱用标签的CSS布局</th><td>少</td><td>一般</td><td>差</td></tr> <tr><th>标签语义良好的 CSS 布局</th><td>少</td><td>好</td><td>好</td></tr>

</tbody> </table>

代码清单 3-17表格模块实现方案二的语义

<表格 border="1"> <表格标题>几种页面实现的比较</表格标题>

</表格头部> <表格主体>

<表格行><表头>table 布局</表头><表格单元格>多</表格单元格><表格单元格>差</表格单元格><表格单元格>一般</表格单元格></表格行>

<表格行><表头>乱用标签的 CSS 布局</表头><表格单元格>少</表格单元格><表格单元格 >一般</表格单元格><表格单元格>差</表格单元格></表格行>

<表格行><表头>标签语义良好的 CSS 布局</表头><表格单元格>少</表格单元格><表格单元格>好</表格单元格><表格单元格>好</表格单元格></表格行>

</表格主体> </table>

3.4.4 语义化标签应注意的一些其他问题

第 4 章高品质的 CSS

本章内容

怪异模式和 DTD

如何组织 CSS

推荐的 base.css

模块化 CSS——引入编程的思想到 CSS

低权重原则——避免滥用子选择器

CSS sprite

CSS 的常见问题

4.1 怪异模式和 DTD

代码清单 4-1 HTML 中常见的 4 种 DTD 类型

用于 HTML 4.01 的严格型 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"

"http://www.w3.org/TR/html4/strict.dtd">

用于 HTML 4.01 的过渡型 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"

"http://www.w3.org/TR/html4/loose.dtd"> 用于 XHTML 1.0 的严格型

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"

"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 用于 XHTML 1.0 的过渡型

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"

"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

4.2 如何组织 CSS

代码清单 4-2 page.css 的注释

/*首页*/ .test{}

.test2{}

/*关于我们*/ .test3{}

.test4{}

/*联系我们*/ .test5{}

.test6{}

4.3 推荐的 base.css

代码清单 4-3 base.css

.mb5{margin-bottom:5px}/*CSS reset*/ body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,fieldset,input,textarea,p,

blockquote,th,td {margin:0;padding:0;} table {border-collapse:collapse;border-spacing:0;}

fieldset,img {border:0} address,caption,cite,code,dfn,em,strong,th,var

{font-style:normal;font-weight:normal} ol,ul {list-style:none}

caption,th {text-align:left} h1,h2,h3,h4,h5,h6 {font-size:100%;font-weight:normal}

q:before,q:after {content:''} abbr,acronym { border:0}

/*文字排版*/ .f12{font-size:12px}

.f13{font-size:13px} .f14{font-size:14px}

.f16{font-size:16px} .f20{font-size:20px}

.fb{font-weight:bold} .fn{font-weight:normal}

.t2{text-indent:2em} .lh150{line-height:150%}

.lh180{line-height:180%} .lh200{line-height:200%}

.unl{text-decoration:underline;} .no_unl{text-decoration:none;}

/*定位*/ .tl{text-align:left}

.tc{text-align:center} .tr{text-align:right}

.bc{margin-left:auto;margin-right:auto;} .fl{float:left;display:inline}

.fr{float:right;display:inline} .cb{clear:both}

.cl{clear:left} .cr{clear:right}

.clearfix:after{content:".";display:block;height:0;clear:both;visibility:hidden} .clearfix{display:inline-block}* html .clearfix{height:1%}.clearfix{display:block}

.vm{vertical-align:middle} .pr{position:relative}

.pa{position:absolute} .abs-right{position:absolute;right:0}

.zoom{zoom:1} .hidden{visibility:hidden}

.none{display:none}

/*长度高度*/ .w10{width:10px}

.w20{width:20px} .w30{width:30px}

.w40{width:40px} .w50{width:50px}

.w60{width:60px}

.w100{width:100px} .w200{width:200px}

.w250{width:250px} .w300{width:300px}

.w400{width:400px} .w500{width:500px}

.w600{width:600px} .w700{width:700px}

.w800{width:800px} .w{width:100%}

.h50{height:50px} .h80{height:80px}

.h100{height:100px} .h200{height:200px}

.h{height:100%}

/*边距*/ .m10{margin:10px}

.m15{margin:15px} .m30{margin:30px}

.mt5{margin-top:5px} .mt10{margin-top:10px}

.mt15{margin-top:15px} .mt20{margin-top:20px}

.mt30{margin-top:30px} .mt50{margin-top:50px}

.mt100{margin-top:100px}

.mb10{margin-bottom:10px} .mb15{margin-bottom:15px}

.mb20{margin-bottom:20px} .mb30{margin-bottom:30px}

.mb50{margin-bottom:50px} .mb100{margin-bottom:100px}

.ml5{margin-left:5px} .ml10{margin-left:10px}

.ml15{margin-left:15px} .ml20{margin-left:20px}

.ml30{margin-left:30px} .ml50{margin-left:50px}

.ml100{margin-left:100px} .mr5{margin-right:5px}

.mr10{margin-right:10px} .mr15{margin-right:15px}

.mr20{margin-right:20px} .mr30{margin-right:30px}

.mr50{margin-right:50px} .mr100{margin-right:100px}

.p10{padding:10px;} .p15{padding:15px;}

.p30{padding:30px;} .pt5{padding-top:5px}

.pt10{padding-top:10px} .pt15{padding-top:15px}

.pt20{padding-top:20px} .pt30{padding-top:30px}

.pt50{padding-top:50px}

.pb20{padding-bottom:20px} .pb30{padding-bottom:30px}

.pb50{padding-bottom:50px} .pb100{padding-bottom:100px}

.pl5{padding-left:5px} .pl10{padding-left:10px}

.pl15{padding-left:15px} .pl20{padding-left:20px}

.pl30{padding-left:30px} .pl50{padding-left:50px}

.pl100{padding-left:100px} .pr5{padding-right:5px}

.pr10{padding-right:10px} .pr15{padding-right:15px}

.pr20{padding-right:20px} .pr30{padding-right:30px}

.pr50{padding-right:50px} .pr100{padding-right:100px}

4.4 模块化 CSS —— 引入面向对象的编程思想到 CSS

4.4.1 如何划分模块 —— 单一职责

4.4.2CSS 的命名 —— 命名空间的概念

代码清单 4-4css 命名方案一

<style type=”text/CSS”> .timeList{xxxxxxx}

</style> <ul class=”timelist”>

<li>2009 年 08 月(3)</li> <li>2009 年 07 月(12)</li>

<li>2009 年 06 月(3)</li> <li>2009 年 05 月(8)</li>

<li>2009 年 04 月(2)</li> <li>2009 年 03 月(8)</li>

</ul>

代码清单 4-5css 命名方案二

<style type=”text/CSS”> .timeList{xxxxxxx}

.timeList li{border-bottom:xxxx;} .timeList .last{border-bottom:none;}

</style> <ul class=”timeList”>

<li>2009 年 08 月(3)</li> <li>2009 年 07 月(12)</li>

<li>2009 年 06 月(3)</li> <li>2009 年 05 月(8)</li>

<li>2009 年 04 月(2)</li> <li class=”last”>2009 年 03 月(8)</li>

</ul>

代码清单 4-6css 命名方案三

<style type=”text/CSS”>

</style> <ul class=”timeList”>

<li>2009 年 08 月(3)</li> <li>2009 年 07 月(12)</li>

<li>2009 年 06 月(3)</li> <li>2009 年 05 月(8)</li>

<li>2009 年 04 月(2)</li> <li class=”timeListLastItem”>2009 年 03 月(8)</li>

</ul>

代码清单 4-7css 命名冲突

<style type=”text/CSS”> /*made by 工程师 A*/

.timeList{xxxxxxx} .timeList li{border-bottom:xxxx;}

.timeList-lastItem{border-bottom:none;}

...

/*made by 工程师 B*/ .timeList{}

.timeList li{border-bottom:xxxx;}

</style> <!--made by 工程师 A-->

<ul class=”timeList”> <li>2009 年 08 月(3)</li>

<li>2009 年 07 月(12)</li> <li>2009 年 06 月(3)</li>

<li>2009 年 05 月(8)</li> <li>2009 年 04 月(2)</li>

<li class=”timeList-lastItem”>2009 年 03 月(8)</li> </ul>

...

<!--made by 工程师 B--> <ol class=”timeList”>

<li>2009-08-07</li> <li>2009-08-06 </li>

<li>2009-08-05</li> </ol>

代码清单 4-8css 命名加前辍

<style type=”text/CSS”> /*made by 工程师 A*/

.ad-timeList{xxxxxxx} .ad-timeList li{border-bottom:xxxx;}

.ad-timeList-lastItem{border-bottom:none;}

...

/*made by 工程师 B*/ .zx-timeList{}

.zx-timeList li{border-bottom:xxxx;}

</style>

<li>2009 年 07 月(12)</li> <li>2009 年 06 月(3)</li>

<li>2009 年 05 月(8)</li> <li>2009 年 04 月(2)</li>

<li class=”ad-timeList-lastItem”>2009 年 03 月(8)</li> </ul>

...

<!--made by 工程师 B--> <ol class=”zx-timeList”>

<li>2009-08-07</li> <li>2009-08-06 </li>

<li>2009-08-05</li> </ol>

代码清单 4-9不加前辍的命名方式

<div=”box”> <div class=”hd”></div>

<div class=”bd”></div> <div class=”ft”></div>

</div>

代码清单 4-10加前辍的命名方式

<div=”box”> <div class=”box-hd”></div>

<div class=”box-bd”></div> <div class=”box-ft”></div>

</div>

4.4.3挂多个 class 还是新建 class ——多用组合,少用继承

代码清单 4-11三个简单模块实现方案一

<style type=”text/CSS”> .numberList1{border:1px solid #ccc;padding:10px}

.numberList1 li{height:20px;line-height:20px;font-size:12px} .numberList2{border:1px solid #ccc;padding:10px;}

.numberList2 li{height:20px;line-height:20px;font-size:16px} .numberList3{border:1px solid #ccc;padding:10px;}

.numberList3 li{height:20px;line-height:20px;font-size:12px;color:red} </style>

<body> <ul class="numberList1">

<li>111111111111111111</li> <li>222222222222222222</li>

<li>333333333333333333</li> </ul>

<ul class="numberList2"> <li>444444444444444444</li>

<li>555555555555555555</li> <li>666666666666666666</li>

</ul> <ul class="numberList3">

<li>777777777777777777</li> <li>888888888888888888</li>

代码清单 4-12三个简单模块实现方案二

<style type=”text/CSS”> .numberList1,.numberList2,.numberList3{border:1px solid #ccc;padding:10px}

.numberList1 li,.numberList2 li,.numberList3 li{height:20px;line-height:20px;font-size:12px}

.numberList2 li{font-size:16px} .numberList3 li{color:red}

</style>

<body> <ul class="numberList1">

<li>111111111111111111</li> <li>222222222222222222</li>

<li>333333333333333333</li> </ul>

<ul class="numberList2"> <li>444444444444444444</li>

<li>555555555555555555</li> <li>666666666666666666</li>

</ul> <ul class="numberList3">

<li>777777777777777777</li> <li>888888888888888888</li>

<li>999999999999999999</li> </ul>

</body>

代码清单 4-13三个简单模块实现方案三

<style type=”text/CSS”> .f12{font-size:12px}

.f16{font-size:16px} .red{color:red}

.numberList{border:1px solid #ccc;padding:10px;} .numberList li{height:20px;line-height:20px;}

</style>

<body> <ul class="numberList f12">

<li>111111111111111111</li> <li>222222222222222222</li>

<li>333333333333333333</li> </ul>

<ul class="numberList f16"> <li>444444444444444444</li>

<li>555555555555555555</li> <li>666666666666666666</li>

</ul> <ul class="numberList f12 red">

<li>777777777777777777</li> <li>888888888888888888</li>

<li>999999999999999999</li> </ul>

</body>

代码清单 4-14方案二面对扩展

<style type=”text/CSS”>

.numberList1 li,.numberList2 li.,numberList3 li,numberList4 li {height:20px;line-height:20px;font-size:12px}

.numberList2 li,.numberList4 li{font-size:16px} .numberList3 li,.numberList4 li{color:red}

</style>

<body> <ul class="numberList1">

<li>111111111111111111</li> <li>222222222222222222</li>

<li>333333333333333333</li> </ul>

<ul class="numberList2"> <li>444444444444444444</li>

<li>555555555555555555</li> <li>666666666666666666</li>

</ul> <ul class="numberList3">

<li>777777777777777777</li> <li>888888888888888888</li>

<li>999999999999999999</li> </ul>

<ul class="numberList4"> <li>101010101010101010</li>

<li>111111111111111111</li> <li>121212121212121212</li>

</ul> </body>

代码清单 4-15方案三面对扩展

<style type=”text/CSS”> .f12{font-size:12px}

.f16{font-size:16px} .red{color:red}

.numberList{border:1px solid #ccc;padding:10px;} .numberList li{height:20px;line-height:20px;}

</style>

<body> <ul class="numberList f12">

<li>111111111111111111</li> <li>222222222222222222</li>

<li>333333333333333333</li> </ul>

<ul class="numberList f16"> <li>444444444444444444</li>

<li>555555555555555555</li> <li>666666666666666666</li>

</ul> <ul class="numberList f12 red">

<li>777777777777777777</li> <li>888888888888888888</li>

<li>999999999999999999</li> </ul>

<ul class="numberList f16 red"> <li>101010101010101010</li>

<li>111111111111111111</li>

代码清单 4-16YUI3 中的 class

<div class="yui-widget yui-overlay yui-widget-positioned yui-widget-stacked"> <!--Bounding Box-->

<div class="yui-overlay-content yui-widget-stdmod"> <!--Content Box-->

<div class="yui-widget-hd">Overlay Header Content</div><!--Header Section-->

<div class="yui-widget-bd">Overlay Body Content</div><!--Body Section-->

<div class="yui-widget-ft">Overlay Footer Content</div><!--Footer Section-->

</div>

<iframe class="yui-widget-shim"></iframe><!-- Stacking shim, if enabled-->

</div>

4.4.4如何处理上下 margin

代码清单 4-17提取标题组件

<style type=”text/CSS”> .title{border-bottom:1px dashed

#B2BCC6;color:#0066CF;font-size:16px;font-weight:bold;} </style>

<h2 class=”title”>服务理念</h2> …

<h2 class=”title”>服务宗旨</h2> …

<h2 class=”title”>Gsns 产品的优势</h2> …

代码清单 4-18包含 margin 的标题组件

<style type=”text/CSS”> .title1{border-bottom:1px dashed

#B2BCC6;color:#0066CF;font-size:16px;font-weight:bold;margin-top:20px;} .title2{border-bottom:1px dashed

#B2BCC6;color:#0066CF;font-size:16px;font-weight:bold;margin-top:60px;} </style>

<h2 class=”title1”>服务理念</h2> …

<h2 class=”title1”>服务宗旨</h2> …

<h2 class=”title2”>Gsns 产品的优势</h2> …

代码清单 4-19应用类的组合

<style type=”text/CSS”> .mt20{margin-top:20px;}

.mt60{margin-top:60px;}

</style>

<h2 class=”title mt20”>服务理念</h2> …

<h2 class=”title mt20”>服务宗旨</h2> …

<h2 class=”title mt60”>Gsns 产品的优势</h2> …

4.5低权重原则 —— 避免滥用子选择器

代码清单 4-20css 的层叠

<style type=”text/CSS”> span{font-size:40px}

.test{color:red} </style>

<span class=”test”>1234567890</span>

代码清单 4-21css 层叠有冲突的情况

<style type=”text/CSS”> span{font-size:40px;color:green}

.test{color:red} </style>

<span class=”test”>1234567890</span>

代码清单 4-22选择符权重相同的情况

<style type=”text/CSS”> span{font-size:40px}

.test{color:red} .test2{color:green}

</style>

<span class=”test test2”>1234567890</span>

代码清单 4-23调换样式的位置

<style type=”text/CSS”> span{font-size:40px}

.test2{color:green} .test{color:red}

</style>

<span class=”test test2”>1234567890</span>

代码清单 4-24需标红的代码

<style type=”text/CSS”> #test{font-size:14px;}

</style> <p id=”test”>CSS 选择符权重很重要</p>

代码清单 4-25用子选择器

<style type=”text/CSS”> #test{font-size:14px;}

代码清单 4-26新建 class

<style type=”text/CSS”> #test{font-size:14px;}

.font{color:red;} </style>

<p id=”test”>CSS 选择符权重<span class=”font”>很重要</span></p>

代码清单 4-27添加新的文本

<style type=”text/CSS”> #test{font-size:14px;}

#test span{color:red;} </style>

<p id=”test”>CSS 选择符权重<span>很重要</span>,我们要小心处理</p>

代码清单 4-28需标绿的代码

<style type=”text/CSS”> #test{font-size:14px;}

#test span{color:red;} .font{color:green;}

</style> <p id=”test”>CSS 选择符权重<span>很重要</span>,我们要<span class=”font”>小心处理

</span></p>

代码清单 4-29被迫加重权重的选择器

<style type=”text/CSS”> #test{font-size:14px;}

#test span{color:red;}/*选择符权重为 100+1=101*/ #test .font{color:green;}/*选择符权重为 100+10=110*/

</style> <p id=”test”>CSS 选择符权重<span>很重要</span>,我们要<span class=”font”>小心处理

</span></p>

代码清单 4-30新增 class 作为标绿容器的选择符

<style type=”text/CSS”> #test{font-size:14px;}

.font{color:red;} .font2{color:green;}

</style> <p id=”test”>CSS 选择符权重<span class=”font”>很重要</span>,我们要<span class=”font2”>

小心处理</span></p>

4.6 CSS sprite

代码清单 4-31用两张图实现高亮

<style type=”text/CSS”> .nav li{float:left; display:inline; margin-right:10px; font-family:黑体;}

.nav a{float:left; width:139px; height:31px; line-height:31px; font-size:24px;

color:#fff; text-decoration:none; text-align:center; background:url(img1.gif);} .nav a:hover{background:url(img2.gif);}

</style> <ulclass="nav">

<li><a href="#">联系我们</a></li> <li><a href="#">产品答疑</a></li>

代码清单 4-32利用一张大图的背景移动实现高亮

<style type=”text/CSS”> .nav li{float:left; display:inline; margin-right:10px; font-family:黑体;}

.nav a{float:left; width:139px; height:31px; line-height:31px; font-size:24px;

color:#fff; text-decoration:none; text-align:center; background:url(img3.gif);} .nav a:hover{background-position:0 -31px;}

</style> <ulclass="nav">

<li><a href="#">联系我们</a></li> <li><a href="#">产品答疑</a></li>

<li><a href="#">广告服务</a></li> </ul>

4.7 CSS 的常见问题

4.7.1 CSS 的编码风格

代码清单 4-33多行式的 css 编码风格

.test{ width:100px;

height:50px;

color:#ccc;

} .demo{

background-color:green;

font-size:20px;

}

代码清单 4-34一行式的 css 编码风格

.test{width:100px;height:50px;color:#ccc;} .demo{background-color:green;font-size:20px;}

4.7.2id 和 class

4.7.3CSS hack

代码清单 4-35只在 IE 下生效

<!--[if IE]> <link type="text/CSS" href="test.css" rel="stylesheet" />

<![endif]-->

代码清单 4-36只在 IE6 下生效

<!--[if IE 6]> <link type="text/CSS" href="test.css" rel="stylesheet" />

<![endif]-->

代码清单 4-37只在 IE6 以上版本生效

<!--[if gt IE 6]> <link type="text/CSS" href="test.css" rel="stylesheet" />

<![endif]-->

代码清单 4-38只在 IE7 上不生效

<!--[if ! IE 7]>

代码清单 4-39条件注释和 style 标签

<!--[if IE 6]> <style type=”text/CSS”>

.test{} </style>

<![endif]-->

代码清单 4-40条件注释和 script 标签

<!--[if IE 6]> <script type=”text/JavaScript”>

alert(“我是 IE 6”);

</script> <![endif]-->

代码清单 4-41ie6.css、ie7.css 和 ie8.css

  1. ie6.css

.test{width:60px;}

  1. ie7.css

.test{width:70px;}

  1. IE 8.css

.test{width:80px;}

代码清单 4-42针对不同 IE 版本分别导入样式

<!--[if IE 6]> <link type="text/CSS" href="ie6.css" rel="stylesheet" />

<![endif]--> <!--[if gt IE 7]>

<link type="text/CSS" href="ie7.css" rel="stylesheet" /> <![endif]-->

<!--[if gt IE 8]> <link type="text/CSS" href="IE 8.css" rel="stylesheet" />

<![endif]-->

代码清单 4-43选择符前辍 hack 法

<style type=”text/CSS”>

.test{width:80px;}/*IE 6,IE 7,IE 8*/
*html .test{width:60px;}/*only for IE 6*/
*+html .test{width:70px;}/*only for IE 7*/

</style>

代码清单 4-44样式属性前辍 hack 法

<style type=”text/CSS”> .test{width:80px;*width:70px;_width:60px;}

</style>

4.7.4 超链接访问过后 hover 样式就不出现的问题

代码清单 4-45不正确的伪类顺序

<style type="text/CSS"> a:hover{color:yellow;}

a:visited{color:green;} </style>

<a href=”#”>hello world</a>

代码清单 4-46正确的伪类顺序

</style> <a href=”#”>hello world</a>

4.7.5hasLayout

4.7.6 块级元素和行内元素的区别

代码清单 4-47块级元素和行内元素

<style type="text/CSS"> p{background:red}

div{background:yellow} span{background:blue}

strong{background:green} </style>

<p>块级元素 p</p><div>块级元素 div</div><span>行内元素 span</span><strong>行内元素 strong</strong>

代码清单 4-48对块级元素和行内元素设置长宽

<style type="text/CSS"> p{background:red;width:200px;height:200px;}

div{background:yellow;width:400px;height:100px;} span{background:blue;width:200px;height:200px;}

strong{background:green;width:400px;height:100px;} </style>

<p>块级元素 p</p><div>块级元素 div</div><span>行内元素 span</span><strong>行内元素 strong</strong>

代码清单 4-49块级元素、行内元素的 margin 和 padding

<style type="text/CSS"> p{background:red;padding:20px;margin:20px;}

div{background:yellow;padding:20px;} span{background:blue;padding:20px;margin:20px;}

strong{background:green;padding:20px;margin:20px;} </style>

<p>块级元素 p</p><div>块级元素 div</div><span>行内元素 span</span><strong>行内元素 strong</strong>

代码清单 4-50改变块级元素和行内元素的显示

<style type="text/CSS"> p{background:red;display:inline;}

div{background:yellow;display:inline;} span{background:blue;display:block;}

strong{background:green;display:block;} </style>

<p>块级元素 p</p><div>块级元素 div</div><span>行内元素 span</span><strong>行内元素 strong</strong>

4.7.7display:inline-block 和 hasLayout

代码清单 4-51设置 display:inline-block

<style type="text/CSS"> p{color:red;width:100px;background:#ccc;height:30px;display:inline-block;}

</style> <body>

abcdefg <p>12345</p>

<style type="text/CSS"> span{color:red;width:100px;background:#ccc;height:30px;display:inline-block;}

</style> <body>

abcdefg <span>12345</span> </body>

代码清单 4-53调整竖直排列的位置

<style type="text/CSS"> span{color:red;width:100px;background:#ccc;height:30px;display:inline-block;*

vertical-align:-10px;} </style>

<body> abcdefg <span>12345</span>

</body>

4.7.8relative、absolute 和 float

4.7.9居中

代码清单 4-54行内元素的水平居中

<style type="text/CSS"> .wrap{background:#000; width:500px; height:100px; margin-bottom:10px; color:#fff;

text-align:center} </style>

<div class=”wrap”>hello world</div> <div class=”wrap”><img src=”test.gif” /></div>

代码清单 4-55确定宽度的块级元素的水平居中

<style type="text/CSS"> .wrap{background:#000; width:500px; height:100px}

.test{background:red; width:200px; height:50px; margin-left:auto;

margin-right:auto} </style>

<div class=”wrap”><div class=”test”></div></div>

代码清单 4-56 不确定宽度的块级元素的水平居中方法一

<style type="text/CSS"> ul{list-style:none; margin:0; padding:0}

table{margin-left:auto; margin-right:auto;} .test li{float:left; display:inline; margin-right:5px;}

.test a{float:left; width:20px; height:20px; text-align:center; line-height:20px;

background:#316AC5; color:#fff; border:1px solid #316AC5; text-decoration:none;} .test a:hover{background:#fff; color:#316AC5}

</style>

<div class=”wrap”> <table><tbody><tr><td>

<ul class="test"> <li><a href="#">1</a></li>

</ul> </td></tr></tbody></table>

<table><tbody><tr><td> <ul class="test">

</ul> </td></tr></tbody></table>

<table><tbody><tr><td> <ul class="test">

<li><a href="#">1</a></li> <li><a href="#">2</a></li>

<li><a href="#">3</a></li> <li><a href="#">4</a></li>

<li><a href="#">5</a></li> </ul>

</td></tr></tbody></table>

</div>

代码清单 4-57不确定宽度的块级元素的水平居中方法二

<style type="text/CSS"> ul{list-style:none;margin:0;padding:0}

.wrap{background:#000; width:500px; height:100px} .test{text-align:center;padding:5px;}

.test li{display:inline;} .test a{padding:2px 6px;background:#316AC5;color:#fff;border:1px solid

#316AC5;text-decoration:none;} .test a:hover{background:#fff;color:#316AC5}

</style>

<div class="wrap"> <ul class="test">

<li><a href="#">1</a></li> </ul>

<ul class="test"> <li><a href="#">1</a></li>

<li><a href="#">2</a></li> <li><a href="#">3</a></li>

</ul> <ul class="test">

<li><a href="#">1</a></li> <li><a href="#">2</a></li>

<li><a href="#">3</a></li> <li><a href="#">4</a></li>

<li><a href="#">5</a></li> </ul>

</div>

代码清单 4-58不确定宽度的块级元素的水平居中方法三

<style type="text/CSS"> ul{list-style:none; margin:0; padding:0}

.wrap{background:#000; width:500px; height:100px} .test{clear:both; padding-top:5px; float:left; position:relative; left:50%;}

.test li{float:left; display:inline; margin-right:5px; position:relative;

left:-50%;} .test a{float:left; width:20px; height:20px; text-align:center; line-height:20px;

background:#316AC5; color:#fff; border:1px solid #316AC5; text-decoration:none;} .test a:hover{background:#fff; color:#316AC5}

</style>

<div class="wrap"> <ul class="test">

<li><a href="#">1</a></li> <li><a href="#">2</a></li>

<li><a href="#">3</a></li> </ul>

<ul class="test"> <li><a href="#">1</a></li>

<li><a href="#">2</a></li> <li><a href="#">3</a></li>

<li><a href="#">4</a></li> <li><a href="#">5</a></li>

</ul> </div>

代码清单 4-59父元素高度不确定的文本、图片、块级元素的竖直居中

<style type="text/CSS"> .wrap{background:#000; width:500px; color:#fff; margin-bottom:10px;

padding-top:20px; padding-bottom:20px} .test{width:200px;height:50px;background:red;}

</style>

<div class="wrap">hello world</div> <div class="wrap"><img src="54.gif" /></div>

<div class="wrap"><div class="test"></div></div>

代码清单 4-60父元素高度确定的单行文本的竖直居中

<style type="text/CSS"> .wrap{background:#000; width:500px; color:#fff;height:100px;line-height:100px;}

</style>

<div class="wrap">hello world</div>

代码清单 4-61父元素高度确定的多行文本、图片、块级元素的竖直居中方法一

<style type="text/CSS"> .wrap{background:#000; width:500px; color:#fff;height:100px}

.test{width:200px;height:50px;background:red;} </style>

<table><tbody><tr><td class="wrap"> hello world<br />

hello world<br /> hello world

</td></tr></tbody></table>

<table><tbody><tr><td class="wrap"> <img src="54.gif" />

</td></tr></tbody></table>

<table><tbody><tr><td class="wrap"> <div class="test"></div>

</td></tr></tbody></table>

代码清单 4-62父元素高度确定的多行文本、图片、块级元素的竖直居中方法二

<style type="text/CSS"> .mb10{margin-bottom:10px}

.wrap{background:#000; width:500px;

color:#fff;margin-bottom:10px;height:100px;display:table-cell;vertical-align:middle

.vertical{*position:relative;*top:-50%} </style>

<div class="mb10"> <div class="wrap">

<div class="verticalWrap"> <div class="vertical">

hello world<br /> hello world<br />

hello world </div>

</div> </div>

</div> <div class="mb10">

<div class="wrap"> <div class="verticalWrap">

<img src="54.gif" class="vertical" /> </div>

</div> </div>

<div class="mb10"> <div class="wrap">

<div class="verticalWrap"> <div class="test vertical"></div>

</div> </div>

</div>

4.7.10 网格布局

代码清单 4-63两栏式布局方案一

<style type="text/CSS"> .header{}

.footer{clear:both} .sidebar{width:25%; float:left}

.main{width:70%; float:right} </style>

<div class=”header”></div> <div class=”content”>

<div class=”sidebar”></div> <div class=”main”></div>

</div> <div class=”footer”></div>

代码清单 4-64两栏式布局方案二

<style type="text/CSS"> .header{}

.footer{clear:both} .sidebar{width:25%; float:left}

.main{width:70%; float:right} </style>

<div class=”header”></div> <div class=”content”>

<div class=”main”></div>

代码清单 4-65调换左右两栏的位置

<style type="text/CSS"> .header{}

.footer{clear:both} .sidebar{width:25%; float:right}

.main{width:70%; float:left} </style>

<div class=”header”></div> <div class=”content”>

<div class=”main”></div> <div class=”sidebar”></div>

</div> <div class=”footer”></div>

代码清单 4-66用类的组合的方式设定浮动方向

<style type="text/CSS"> .fl{float:left}

.fr{float:right} .header{}

.footer{clear:both} .sidebar{width:25%}

.main{width:70%} </style>

<div class=”header”></div> <div class=”content”>

<div class=”main fr”></div> <div class=”sidebar fl”></div>

</div> <div class=”footer”></div>

代码清单 4-67用类的组合的方式面对简单修改

<style type="text/CSS"> .fl{float:left}

.fr{float:right} .header{}

.footer{clear:both} .sidebar{width:25%}

.main{width:70%} </style>

<div class=”header”></div> <div class=”content”>

<div class=”main fl”></div> <div class=”sidebar fr”></div>

</div> <div class=”footer”></div>

代码清单 4-68用类的组合的方式面对复杂修改

<style type="text/CSS"> .fl{float:left}

.fr{float:right} .content{clear:both}

.header{}

</style>

<div class=”header”></div> <div class=”content”>

<div class=”main fl”></div> <div class=”sidebar fr”></div>

</div> <div class=”content”>

<div class=”main fr”></div> <div class=”sidebar fl”></div>

</div> <div class=”footer”></div>

代码清单 4-69将宽度提取出来

<style type="text/CSS"> .fl{float:left}

.fr{float:right} .content{clear:both}

.header{} .footer{clear:both}

.sidebar{} .main{}

.w25{width:25%} .w70{width:70%}

.w35{width:35%} .w60{width:60%}

</style>

<div class=”header”></div> <div class=”content”>

<div class=”main fl w70”></div> <div class=”sidebar fr w25”></div>

</div> <div class=”content”>

<div class=”main fr w60”></div> <div class=”sidebar fl w35”></div>

</div> <div class=”footer”></div>

代码清单 4-70用子选择器应对复杂变化

<style type="text/CSS"> .content{clear:both}

.header{} .footer{clear:both}

.main{} .sidebar{}

.content-lr-7025 .main{float:left; width:70%} .content-lr-7025 .sidebar{float:right; width:25%}

.content-rl-7025 .main{float:right; width:70%} .content-rl-7025 .sidebar{float:left; width:25%}

.content-lr-6035 .main{float:left; width:60%} .content-lr-6035 .sidebar{float:right; width:35%}

.content-rl-6035 .main{float:right; width:60%} .content-rl-6035 .sidebar{float:left; width:35%}

</style>

<div class=”header”></div>

</div> <div class=”content content-rl-6035”>

<div class=”main”></div> <div class=”sidebar”></div>

</div> <div class=”footer”></div>

代码清单 4-71组合类的方式面对扩展

<style type="text/CSS"> .fl{float:left}

.fr{float:right} .content{clear:both}

.header{} .footer{clear:both}

.sidebar{} .main{}

.w25{width:25%} .w70{width:70%}

.w35{width:35%} .w60{width:60%}

.w80{width:80%} .w15{width:15%}

</style>

<div class=”header”></div> <div class=”content”>

<div class=”main fl w70”></div> <div class=”sidebar fr w25”></div>

</div> <div class=”content”>

<div class=”main fr w60”></div> <div class=”sidebar fl w35”></div>

</div> <div class=”content”>

<div class=”main fl w80”></div> <div class=”sidebar fr w15”></div>

</div> <div class=”footer”></div>

代码清单 4-72子选择器方式面对扩展

<style type="text/CSS"> .content{clear:both}

.header{} .footer{clear:both}

.main{} .sidebar{}

.content-lr-7025 .main{float:left; width:70%} .content-lr-7025 .sidebar{float:right; width:25%}

.content-rl-7025 .main{float:right; width:70%} .content-rl-7025 .sidebar{float:left; width:25%}

.content-lr-6035 .main{float:left; width:60%} .content-lr-6035 .sidebar{float:right; width:35%}

.content-rl-6035 .main{float:right; width:60%} .content-rl-6035 .sidebar{float:left; width:35%}

.content-lr-8015 .main{float:left; width:80%} .content-lr-8015 .sidebar{float:right; width:15%}

.content-rl-8015 .main{float:right; width:80%}

<div class=”header”></div> <div class=”content content-lr-7025”>

<div class=”main”></div> <div class=”sidebar”></div>

</div> <div class=”content content-rl-6035”>

<div class=”main”></div> <div class=”sidebar”></div>

</div> <div class=”content content-lr-8015”>

<div class=”main”></div> <div class=”sidebar”></div>

</div> <div class=”footer”></div>

代码清单 4-73子选择器布局的嵌套使用

<style type="text/CSS"> .content{clear:both}

.header{} .footer{clear:both}

.main{} .sidebar{}

.content-lr-7025 .main{float:left; width:70%} .content-lr-7025 .sidebar{float:right; width:25%}

.content-rl-7025 .main{float:right; width:70%} .content-rl-7025 .sidebar{float:left; width:25%}

</style>

<div class=”header”></div> <div class=”content content-lr-7025”>

<div class=”main content-lr-7025”> <div class=”main”></div>

<div class=”sidebar”></div> </div>

<div class=”sidebar”></div> </div>

<div class=”footer”></div>

4.7.11 z-index 和 Flash、IE 6 下的 select

代码清单 4-74z-index 设置高低

<style type="text/CSS"> #one{width:300px;height:300px; background:black}

#two{width:100px;height:100px; background:red;position:absolute; z-index:1;

left:100px; top:250px} #three{width:100px;height:100px; background:green; position:relative; z-index:2;

left:120px; top:-100px} </style>

<div id="one"></div> <div id="two"></div>

<div id="three"></div>

代码清单 4-75调整 z-index 的高低

<style type="text/CSS">

#three{width:100px; height:100px; background:green; position:relative; z-index:2;

left:120px; top:-100px} </style>

<div id="one"></div> <div id="two"></div>

<div id="three"></div>

代码清单 4-76z-index 设为负数

<style type="text/CSS"> #one{width:300px;height:300px; background:black}

#two{width:100px;height:100px; background:red;position:absolute; z-index:-1;

left:100px; top:250px} #three{width:100px;height:100px; background:green; position:relative; z-index:2;

left:120px; top:-100px} </style>

<div id="one"></div> <div id="two"></div>

<div id="three"></div>

代码清单 4-77为 one、two、three 监听 click 事件

<script type="text/JavaScript"> var one = document.getElementById("one"), two = document.getElementById("two"),

three = document.getElementById("three");

one.onclick = function(){ alert("one");

} two.onclick = function(){

alert("two");

} three.onclick = function(){

alert("three");

}

代码清单 4-78z-index 值相同

<style type="text/CSS"> #two{width:100px;height:100px; background:red;position:absolute; z-index:2;

left:100px; top:250px} #three{width:100px;height:100px; background:green; position:relative; z-index:2;

left:120px; top:-100px} </style>

<div id="two"></div> <div id="three"></div>

代码清单 4-79负边距引起的竖直重叠

<style type="text/CSS"> #one{width:300px; height:300px; background:black}

#two{width:100px; height:100px; background:red; margin-top:-50px} </style>

<div id="one"></div> <div id="two"></div>

代码清单 4-80负边距引起的水平重叠

<style type="text/CSS">

</style>

<div id="one"></div> <div id="two"></div>

代码清单 4-81设置 flash 的显示模式

<object width="640" height="90" type="application/x-shockwave-Flash"

classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"> <param value="xxxxxx.swf" name="movie"></param>

<param value="opaque" name="wmode"></param> <embed width="640" height="90" wmode="opaque"

type="application/x-shockwave-Flash"src="xxxxxx.swf.swf"></embed> </object>

代码清单 4-82select 表单元素

<style type="text/CSS"> #test{width:200px; height:200px; background:green; position:absolute; left:50px;

top:10px;} </style>

<select><option>-请选择-</option></select> <div id="test"></div>

代码清单 4-83用 iframe 解决 IE6 下 select 与浮起元素的显示 bug

<style type="text/CSS"> #test{width:200px; height:200px; background:green; position:absolute; left:50px;

top:10px; z-index:2} #testMask{width:200px; height:200px; position:absolute; left:50px; top:10px;

z-index:1;} </style>

<select><option>-请选择-</option></select> <div id="test"></div>

<iframe id="testMask" frameborder="0" scrolling="no"></iframe>

4.7.12 IE 6 和 png 图片

代码清单 4-84插入 png 图片

<img src=”test.png” />

代码清单 4-85一次性解决 png 透明度在 IE6 下显示问题的脚本

function correctPNG()

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

{ var img = document.images[i]

var imgName = img.src.toUpperCase()

if (imgName.substring(imgName.length-3, imgName.length) == "PNG")

{ var imgID = (img.id) ? "id='" + img.id + "' " : ""

var imgClass = (img.className) ? "class='" + img.className + "' " : ""

var imgTitle = (img.title) ? "title='" + img.title + "' " : "title='" + img.alt

  • "' "

var imgStyle = "display:inline-block;" + img.style.cssText if (img.align == "left") imgStyle = "float:left;" + imgStyle

if (img.align == "right") imgStyle = "float:right;" + imgStyle if (img.parentElement.href) imgStyle = "cursor:hand;" + imgStyle

var strNewHTML = "<span " + imgID + imgClass + imgTitle

  • "(src=\'" + img.src + "\', sizingMethod='scale');\"></span>"

img.outerHTML = strNewHTML i = i-1

} }

} function alphaBackgrounds(){

var rslt = navigator.appVersion.match(/MSIE (d+.d+)/, '');

var itsAllGood = (rslt != null && Number(rslt[1]) >= 5.5);

for (i=0; i<document.all.length; i++){ var bg = document.all[i].currentStyle.backgroundImage;

if (bg){ if (bg.match(/.png/i) != null){

var mypng = bg.substring(5,bg.length-2);

document.all[i].style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+mypng+"',

sizingMethod='crop')";

document.all[i].style.backgroundImage = "url('')";

} }

} }

if (navigator.platform == "Win32" && navigator.appName == "Microsoft Internet Explorer"

&& window.attachEvent) { window.attachEvent("onload", correctPNG);

window.attachEvent("onload", alphaBackgrounds);

}

4.7.13 多版本 IE 并存方案——CSS 的调试利器 IETester

第 5 章高品质的 JavaScript

本章内容

养成良好的编程习惯

JavaScript 分层概念和 JavaScript 库

编程实用技巧

面向对象编程

其他问题

5.1养成良好的编程习惯

5.1.1团队合作——如何避免 js 冲突

代码清单 5-1工程师甲编写功能 A

<div> xxxxxxxxxxx

</div> <script type=”text/Javascript”>

var a = 123 , b = “hello world”;

… </script>

<div> xxxxxxxxxx

</div>

代码清单 5-2工程师乙添加功能 B

<div> xxxxxxxxxxx

</div> <script type=”text/JavaScript”>

var a = 123 , b = “hello world”;

… </script>

<div> xxxxxxxxxx

</div> <script type=”text/JavaScript”>

var a , c = ”abc”;

… </script>

<div> xxxxxxxxxx

</div>

代码清单 5-3使用匿名函数控制变量的作用域

<div> xxxxxxxxxxx

</div>

… })();

</script> <div>

xxxxxxxxxx </div>

<script type=”text/JavaScript”> (function(){

var a , c = ”abc”;

… })();

</script> <div>

xxxxxxxxxx </div>

代码清单 5-4功能 C 和功能 A 的通信

<div> xxxxxxxxxxx

</div> <script type=”text/JavaScript”>

(function(){ var a = 123 , b = “hello world”;

… var d = “adang is very handsome!”;

d = b + “, ” + d;

… })();

</script> <div>

xxxxxxxxxx </div>

<script type=”text/JavaScript”> (function(){

var a , c = ”abc”;

… })();

</script> <div>

xxxxxxxxxx </div>

代码清单 5-5工程师丙添加功能 C

<div> xxxxxxxxxxx

</div> <script type=”text/JavaScript”>

(function(){ var a = 123 , b = “hello world”;

… })();

</script> <div>

xxxxxxxxxx </div>

<script type=”text/JavaScript”> (function(){

</script> <div>

xxxxxxxxxx </div>

<script type=”text/JavaScript”> (function(){

var d = “adang is very handsome!”;

d = b + “, ” + d;

… })();

</script>

代码清单 5-6利用全局作用域的变量在各匿名函数间搭起桥梁

<div> xxxxxxxxxxx

</div> <script type=”text/JavaScript”>

var str;

</script> <script type=”text/JavaScript”>

(function(){ var a = 123 , str = b = “hello world”;

… })();

</script> <div>

xxxxxxxxxx </div>

<script type=”text/JavaScript”> (function(){

var a , c = ”abc”;

… })();

</script> <div>

xxxxxxxxxx </div>

<script type=”text/JavaScript”> (function(){

var b = str;

var d = “adang is very handsome!”;

d = b + “, ” + d;

… })();

</script>

代码清单 5-7添加新的全局变量

<div> xxxxxxxxxxx

</div> <script type=”text/JavaScript”>

var str,str2;

</script> <script type=”text/JavaScript”>

(function(){ var str2 = a = 123 , str = b = “hello world”;

…

xxxxxxxxxx </div>

<script type=”text/JavaScript”> (function(){

var a , c = ”abc”;

… })();

</script> <div>

xxxxxxxxxx </div>

<script type=”text/JavaScript”> (function(){

var a = str2 , b = str;

var d = “adang is very handsome!”;

d = b + “, ” + d + a;

… })();

</script>

代码清单 5-8用 hash 对象作为全局变量

<div> xxxxxxxxxxx

</div> <script type=”text/JavaScript”>

var GLOBAL = {};

</script> <script type=”text/JavaScript”>

(function(){ var a = 123 , b = “hello world”;

GLOBAL.str2 = a;

GLOBAL.str = b;

… })();

</script> <div>

xxxxxxxxxx </div>

<script type=”text/JavaScript”> (function(){

var a , c = ”abc”;

… })();

</script> <div>

xxxxxxxxxx </div>

<script type=”text/JavaScript”> (function(){

var a = GLOBAL.str2 , b = GLOBAL.str;

var d = “adang is very handsome!”;

d = b + “, ” + d + a;

… })();

</script>

代码清单 5-9全局变量的冲突

<script type=”text/JavaScript”> var GLOBAL = {};

</script> <script type=”text/JavaScript”>

(function(){ var a = 123 , b = “hello world”;

GLOBAL.str2 = a;

GLOBAL.str = b;

… })();

</script> <div>

xxxxxxxxxx </div>

<script type=”text/JavaScript”> (function(){

var a , c = ”abc”;

GLOBAL.str = c;

… })();

</script> <div>

xxxxxxxxxx </div>

<script type=”text/JavaScript”> (function(){

var a = GLOBAL.str2 , b = GLOBAL.str;

var d = “adang is very handsome!”;

d = b + “, ” + d + a;

… })();

</script> <div>

xxxxxxxxxx </div>

<script type=”text/JavaScript”> (function(){

var test = GLOBAL.str;

alert(test);

… })();

</script>

代码清单 5-10使用命名空间

<div> xxxxxxxxxxx

</div> <script type=”text/JavaScript”>

var GLOBAL = {};

</script> <script type=”text/JavaScript”>

(function(){ var a = 123 , b = “hello world”;

GLOBAL.A = {};

GLOBAL.A.str2 = a;

GLOBAL.A.str = b;

…

xxxxxxxxxx </div>

<script type=”text/JavaScript”> (function(){

var a , c = ”abc”;

GLOBAL.B = {};

GLOBAL.B.str = c;

… })();

</script> <div>

xxxxxxxxxx </div>

<script type=”text/JavaScript”> (function(){

var a = GLOBAL.A.str2 , b = GLOBAL.A.str;

var d = “adang is very handsome!”;

d = b + “, ” + d + a;

… })();

</script> <div>

xxxxxxxxxx </div>

<script type=”text/JavaScript”> (function(){

var test = GLOBAL.B.str;

alert(test);

… })();

</script>

代码清单 5-11使用多级命名空间

<div> xxxxxxxxxxx

</div> <script type=”text/JavaScript”>

var GLOBAL = {};

</script> <script type=”text/JavaScript”>

(function(){ var a = 123 , b = “hello world”;

GLOBAL.A = {};

GLOBAL.A.CAT = {};

GLOBAL.A.DOG = {};

GLOBAL.A.CAT.name = “mimi”;

GLOBAL.A.DOG.name = “wangcai”;

GLOBAL.A.CAT.move = function(){

} GLOBAL.A.DOG.move = function(){

} GLOBAL.A.str2 = a;

GLOBAL.A.str = b;

… })();

<div> xxxxxxxxxxx

</div> <script type=”text/JavaScript”>

var GLOBAL = {};

GLOBAL.namespace = function(str){ var arr = str.split("."),o = GLOBAL;

for (i=(arr[0] == "GLOBAL") ? 1 : 0; i<arr.length; i++) { o[arr[i]]=o[arr[i]] || {};

o=o[arr[i]];

} }

</script> <script type=”text/JavaScript”>

(function(){ var a = 123 , b = “hello world”;

GLOBAL.namespace(“A.CAT”);

GLOBAL.namespace(“A.DOG”);

GLOBAL.A.CAT.name = “mimi”;

GLOBAL.A.DOG.name = “wangcai”;

GLOBAL.A.CAT.move = function(){

} GLOBAL.A.DOG.move = function(){

} GLOBAL.A.str2 = a;

GLOBAL.A.str = b;

… })();

</script>

代码清单 5-13使用命名空间解决冲突的完整代码

<div> xxxxxxxxxxx

</div> <script type=”text/JavaScript”>

var GLOBAL = {};

GLOBAL.namespace = function(str){ var arr = str.split("."),o = GLOBAL;

for (i=(arr[0] == "GLOBAL") ? 1 : 0; i<arr.length; i++) { o[arr[i]]=o[arr[i]] || {};

o=o[arr[i]];

} }

</script> <script type=”text/JavaScript”>

(function(){ var a = 123 , b = “hello world”;

GLOBAL.namespace(“A.CAT”);

GLOBAL.namespace(“A.DOG”);

GLOBAL.A.CAT.name = “mimi”;

GLOBAL.A.DOG.name = “wangcai”;

GLOBAL.A.CAT.move = function(){

} GLOBAL.A.DOG.move = function(){

GLOBAL.A.str = b;

… })();

</script> <div>

xxxxxxxxxx </div>

<script type=”text/JavaScript”> (function(){

var a , c = ”abc”;

GLOBAL.namespace(“B”);

GLOBAL.B.str = c;

… })();

</script> <div>

xxxxxxxxxx </div>

<script type=”text/JavaScript”> (function(){

var a = GLOBAL.A.str2 , b = GLOBAL.A.str;

var d = “adang is very handsome!”;

d = b + “, ” + d + a;

… })();

</script> <div>

xxxxxxxxxx </div>

<script type=”text/JavaScript”> (function(){

var test = GLOBAL.B.str;

alert(test);

… })();

</script>

代码清单 5-14给代码添加注释

<div> xxxxxxxxxxx

</div> <script type=”text/JavaScript”>

var GLOBAL = {};

GLOBAL.namespace = function(str){ var arr = str.split("."),o = GLOBAL;

for (i=(arr[0] == "GLOBAL") ? 1 : 0; i<arr.length; i++) { o[arr[i]]=o[arr[i]] || {};

o=o[arr[i]];

} }

</script> <script type=”text/JavaScript”>

//==================================================== //功能 A

//工程师甲

//2009-11-04

GLOBAL.namespace(“A.CAT”);

GLOBAL.namespace(“A.DOG”);

GLOBAL.A.CAT.name = “mimi”;

GLOBAL.A.DOG.name = “wangcai”;

GLOBAL.A.CAT.move = function(){

} GLOBAL.A.DOG.move = function(){

} GLOBAL.A.str2 = a;

GLOBAL.A.str = b;

… })();

</script> <div>

xxxxxxxxxx </div>

<script type=”text/JavaScript”> //====================================================

//功能 B //工程师乙

//email:a@gmail.commsn:a@hotmail.com //2009-11-05

//==================================================== (function(){

var a , c = ”abc”;

GLOBAL.namespace(“B”);

GLOBAL.B.str = c;

… })();

</script> <div>

xxxxxxxxxx </div>

<script type=”text/JavaScript”> //====================================================

//功能 C //工程师丙

//email:b@yahoo.commsn:b@hotmail.com //2009-11-09

//==================================================== (function(){

var a = GLOBAL.A.str2 , b = GLOBAL.A.str;

var d = “adang is very handsome!”;

d = b + “, ” + d + a;

… })();

</script> <div>

xxxxxxxxxx </div>

<script type=”text/JavaScript”> //====================================================

//功能 D //工程师丁

var test = GLOBAL.B.str;

alert(test);

… })();

</script>

5.1.2给程序一个统一的入口——window.onload 和 DOMReady

代码清单 5-15区分 javascript 的框架部分和应用部分

<div> xxxxxxxxxxx

</div> <script type=”text/JavaScript”>

var GLOBAL = {};

GLOBAL.namespace = function(str){ var arr = str.split("."),o = GLOBAL;

for (i=(arr[0] == "GLOBAL") ? 1 : 0; i<arr.length; i++) { o[arr[i]]=o[arr[i]] || {};

o=o[arr[i]];

} }

</script> <script type=”text/JavaScript”>

//==================================================== //功能 A

//工程师甲 //email:cly84920@gmail.com msn:cly84920@hotmail.com

//2009-11-04 //====================================================

(function(){ var a = 123 , b = “hello world”;

GLOBAL.namespace(“A.CAT”);

GLOBAL.namespace(“A.DOG”);

GLOBAL.A.CAT.name = “mimi”;

GLOBAL.A.DOG.name = “wangcai”;

GLOBAL.A.CAT.move = function(){

} GLOBAL.A.DOG.move = function(){

} GLOBAL.A.str2 = a;

GLOBAL.A.str = b;

… })();

</script> <div>

xxxxxxxxxx </div>

<script type=”text/JavaScript”> //====================================================

//功能 B //工程师乙

//2009-11-05 //====================================================

GLOBAL.B.str = c;

… })();

</script> <div>

xxxxxxxxxx </div>

<script type=”text/JavaScript”> //====================================================

//功能 C //工程师丙

//email:b@yahoo.commsn:b@hotmail.com //2009-11-09

//==================================================== (function(){

var a = GLOBAL.A.str2 , b = GLOBAL.A.str;

var d = “adang is very handsome!”;

d = b + “, ” + d + a;

… })();

</script> <div>

xxxxxxxxxx </div>

<script type=”text/JavaScript”> //====================================================

//功能 D //工程师丁

//email:c@126.commsn:c@hotmail.com //2009-11-20

//==================================================== (function(){

var test = GLOBAL.B.str;

alert(test);

… })();

</script>

代码清单 5-16给应用部分一个统一的“入口”

<div> xxxxxxxxxxx

</div> <script type=”text/JavaScript”>

var GLOBAL = {};

GLOBAL.namespace = function(str){ var arr = str.split("."),o = GLOBAL;

for (i=(arr[0] == "GLOBAL") ? 1 : 0; i<arr.length; i++) { o[arr[i]]=o[arr[i]] || {};

o=o[arr[i]];

} }

</script> <script type=”text/JavaScript”>

function init(){ //====================================================

//功能 A //工程师甲

(function(){ var a = 123 , b = “hello world”;

GLOBAL.namespace(“A.CAT”);

GLOBAL.namespace(“A.DOG”);

GLOBAL.A.CAT.name = “mimi”;

GLOBAL.A.DOG.name = “wangcai”;

GLOBAL.A.CAT.move = function(){

} GLOBAL.A.DOG.move = function(){

} GLOBAL.A.str2 = a;

GLOBAL.A.str = b;

… })();

//==================================================== //功能 B

//工程师乙 //email:a@gmail.commsn:a@hotmail.com

//2009-11-05 //====================================================

(function(){ var a , c = ”abc”;

GLOBAL.namespace(“B”);

GLOBAL.B.str = c;

… })();

//==================================================== //功能 C

//工程师丙 //email:b@yahoo.commsn:b@hotmail.com

//2009-11-09 //====================================================

(function(){ var a = GLOBAL.A.str2 , b = GLOBAL.A.str;

var d = “adang is very handsome!”;

d = b + “, ” + d + a;

… })();

//==================================================== //功能 D

//工程师丁 //email:c@126.commsn:c@hotmail.com

//2009-11-20 //====================================================

(function(){ var test = GLOBAL.B.str;

alert(test);

… })();

} </script>

<div>

xxxxxxxxxx </div>

<div> xxxxxxxxxx

</div>

代码清单 5-17在 DOM 节点加载进来之前就调用

<script type="text/JavaScript"> alert(document.getElementById("test").innerHTML);

</script> <div id="test">hello world</div>

代码清单 5-18调整脚本的位置

<div id="test">hello world</div> <script type="text/JavaScript">

alert(document.getElementById("test").innerHTML);

</script>

代码清单 5-19监听 window.onload

<script type="text/JavaScript"> window.onload = function(){

alert(document.getElementById("test").innerHTML);

} </script>

<div id="test">hello world</div>

代码清单 5-20定义初始化方法的名称为 init

<script type="text/JavaScript"> function init(){

alert(document.getElementById("test").innerHTML);

} window.onload = init;

</script> <div id="test">hello world</div>

代码清单 5-21jQuery 中监听 DOMReady

<script type="text/JavaScript"

src="http://ajax.googleAPIs.com/ajax/libs/jquery/1.3/jquery.min.js"></script> <script type="text/JavaScript">

function init(){ alert(document.getElementById("test").innerHTML);

} $(document).ready(init);

</script> <div id="test">hello world</div>

代码清单 5-22YUI 中监听 DOMReady

<script type="text/JavaScript"

src="http://yui.yahooAPIs.com/combo?2.8.0r4/build/yahoo-dom-event/yahoo-dom-event.j s"></script>

<script type="text/JavaScript"> function init(){

alert(document.getElementById("test").innerHTML);

} YAHOO.util.Event.onDOMReady(init);

</script>

<script type="text/JavaScript"> function init(){

alert(document.getElementById("test").innerHTML);

} </script>

<div id="test">hello world</div> …

<script type="text/JavaScript"> init();

</script> </body>

代码清单 5-24调用 init 函数

<div> xxxxxxxxxxx

</div> <script type=”text/JavaScript”>

var GLOBAL = {};

GLOBAL.namespace = function(str){ var arr = str.split("."),o = GLOBAL;

for (i=(arr[0] == "GLOBAL") ? 1 : 0; i<arr.length; i++) { o[arr[i]]=o[arr[i]] || {};

o=o[arr[i]];

} }

</script> <script type=”text/JavaScript”>

function init(){ //====================================================

//功能 A //工程师甲

//email:cly84920@gmail.com msn:cly84920@hotmail.com //2009-11-04

//==================================================== (function(){

var a = 123 , b = “hello world”;

GLOBAL.namespace(“A.CAT”);

GLOBAL.namespace(“A.DOG”);

GLOBAL.A.CAT.name = “mimi”;

GLOBAL.A.DOG.name = “wangcai”;

GLOBAL.A.CAT.move = function(){

} GLOBAL.A.DOG.move = function(){

} GLOBAL.A.str2 = a;

GLOBAL.A.str = b;

… })();

//==================================================== //功能 B

//工程师乙

//2009-11-05 //====================================================

GLOBAL.B.str = c;

… })();

//==================================================== //功能 C

//工程师丙 //email:b@yahoo.commsn:b@hotmail.com

//2009-11-09 //====================================================

(function(){ var a = GLOBAL.A.str2 , b = GLOBAL.A.str;

var d = “adang is very handsome!”;

d = b + “, ” + d + a;

… })();

//==================================================== //功能 D

//工程师丁 //email:c@126.commsn:c@hotmail.com

//2009-11-20 //====================================================

(function(){ var test = GLOBAL.B.str;

alert(test);

… })();

} </script>

<div> xxxxxxxxxx

</div> <div>

xxxxxxxxxx </div>

<div> xxxxxxxxxx

</div> …

<script type="text/JavaScript"> init();

</script> </body>

代码清单 5-25框架部分的代码

<div> xxxxxxxxxxx

</div> <script type=”text/JavaScript”>

var GLOBAL = {};

GLOBAL.namespace = function(str){ var arr = str.split("."),o = GLOBAL;

for (i=(arr[0] == "GLOBAL") ? 1 : 0; i<arr.length; i++) { o[arr[i]]=o[arr[i]] || {};

o=o[arr[i]];

}

function init(){ //应用部分的 JavaScript

} </script>

<div> xxxxxxxxxx

</div> <div>

xxxxxxxxxx </div>

<div> xxxxxxxxxx

</div> …

<script type="text/JavaScript"> init();

</script> </body>

代码清单 5-26头部文件

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"

"http://www.w3.org/TR/html4/strict.dtd"> <html>

<head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

<title>阿当制作</title> <link rel="stylesheet" type="text/CSS" href="xxx.css" />

</head> <body>

<div class="head"> ...

</div> <script type=”text/JavaScript”>

var GLOBAL = {};

GLOBAL.namespace = function(str){ var arr = str.split("."),o = GLOBAL;

for (i=(arr[0] == "GLOBAL") ? 1 : 0; i<arr.length; i++) { o[arr[i]]=o[arr[i]] || {};

o=o[arr[i]];

} }

</script>

代码清单 5-27尾部文件

<div class="foot"> ...

</div> <script type=”text/JavaScript”>

init();

</script>

代码清单 5-28主体文件

<div>...</div> <script type=”text/JavaScript”>

function init(){ //应用部分的 JavaScript

}

<div class="foot"> ...

</div> <script type=”text/JavaScript”>

if(init){ init();

} </script>

5.1.3CSS 放在页头,JavaScript 放在页尾

代码清单 5-30有 JavaScript 和 CSS 的网页

<script type=”text/JavaScript”> window.onload = function(){

//非常多的 js 代码 …

} </script>

<div id=”test”>xxxxx</div> <!—非常多的代码-->

… <style type=”text/CSS”>

#test{} </style>

代码清单 5-31将 CSS 放在页头,JavaScript 放在页尾

<style type=”text/CSS”> #test{}

</style> <div id=”test”>xxxxx</div>

<!—非常多的代码--> …

<script type=”text/JavaScript”> window.onload = function(){

//非常多的 JavaScript 代码 …

} </script>

5.1.4引入编译的概念——文件压缩

代码清单 5-32未压缩的 JavaScript 脚本

//定义两个字符串 var testStr = "hello";

var testStr2 = "world";

//连接字符串函数 function addStr(str,str2){

return str + " " + str2;

} //调用函数,连接定义的两个字符串

addStr(testStr,testStr2);

代码清单 5-33压缩后的 JavaScript 脚本

var testStr="hello";var testStr2="world";function addStr(a,b){return a+"

"+b}addStr(testStr,testStr2);

5.2 JavaScript 的分层概念和 JavaScript 库

5.2.1JavaScript 如何分层

5.2.2base 层

代码清单 5-34简单的代码

<ul> <li id="item1"></li>

<li id="item2"></li> <li id="item3"></li>

</ul> <script type="text/JavaScript">

var item1 = document.getElementById("item1");

alert(item1.nextSibling.id);

</script>

代码清单 5-35查看 IE 和 firefox 下的区别

<ul> <li id="item1"></li>

<li id="item2"></li> <li id="item3"></li>

</ul> <script type="text/JavaScript">

var item1 = document.getElementById("item1");

alert(item1.nextSibling.nodeType);

alert(document.getElementsByTagName("ul")[0].childNodes.length);

</script>

代码清单 5-36去掉空格

<ul><li id="item1"></li><li id="item2"></li><li id="item3"></li></ul> <script type="text/JavaScript">

var item1 = document.getElementById("item1");

alert(item1.nextSibling.id);

</script>

代码清单 5-37分别对 IE 和 firefox 写程序

<ul> <li id="item1"></li>

<li id="item2"></li> <li id="item3"></li>

</ul> <script type="text/JavaScript">

var item1 = document.getElementById("item1");

var nextNode = item1.nextSibling;

//Firefox 不支持 document.all。这里用以判别浏览器类型 if(!document.all){

while(true){ if(nextNode.nodeType == 1){

break;

} else { if(nextNode.nextSibling){

nextNode = nextNode.nextSibling;

} else { break;

} }

</script>

代码清单 5-38针对 IE 和 firefox 分别写程序如何面对扩展

<ul> <li id="item1"></li>

<li id="item2"></li> <li id="item3"></li>

</ul> <script type="text/JavaScript">

var item1 = document.getElementById("item1");

var nextNode = item1.nextSibling;

if(!document.all){ while(true){

if(nextNode.nodeType == 1){ break;

} else { if(nextNode.nextSibling){

nextNode = nextNode.nextSibling;

} else { break;

} }

} }

alert(nextNode.id);

var item2 = document.getElementById("item2");

var nextNode2 = item2.nextSibling;

if(!document.all){ while(true){

if(nextNode2.nodeType == 1){ break;

} else { if(nextNode2.nextSibling){

nextNode2 = nextNode2.nextSibling;

} else { break;

} }

} }

alert(nextNode2.id);

</script>

代码清单 5-39用 getNextNode 函数封装 IE 和 firefox 的差异

<ul> <li id="item1"></li>

<li id="item2"></li> <li id="item3"></li>

</ul> <script type="text/JavaScript">

function getNextNode(node){ node = typeof node == "string" ? document.getElementById(node) : node;

var nextNode = node.nextSibling;

if(!nextNode) return null;

if(!document.all){ while(true){

if(nextNode.nextSibling){ nextNode = nextNode.nextSibling;

} else { break;

} }

} }

return nextNode;

};

var nextNode = getNextNode("item1");

alert(nextNode.id);

var nextNode2 = getNextNode("item2");

alert(nextNode2.id);

</script>

代码清单 5-40针对 IE 和 firefox 分别设置透明度

<style type="text/CSS"> #test1{background:blue;height:100px;}

#test2{background:green;height:100px;} </style>

<div id="test1"></div> <div id="test2"></div>

<script type="text/JavaScript"> var test1 = document.getElementById("test1"),test2 =

document.getElementById("test2");

if (document.all){ test1.style.filter = 'alpha(opacity=20)';

test2.style.filter = 'alpha(opacity=80)';

} else { test1.style.opacity = 0.2;

test2.style.opacity = 0.8;

} </script>

代码清单 5-41封装 setOpacity 函数

<style type="text/CSS"> #test1{background:blue;height:100px;}

#test2{background:green;height:100px;} </style>

<div id="test1"></div> <div id="test2"></div>

<script type="text/JavaScript"> function setOpacity(node, level){

node = typeof node == "string" ? document.getElementById(node) : node;

if (document.all){ node.style.filter = 'alpha(opacity=' + level + ')';

} else { node.style.opacity = level / 100;

} }

setOpacity("test1",20);

setOpacity("test2",80);

</script>

代码清单 5-42点击事件和参数

<input type="button" value="click me" id="btn" />

alert(arguments.length);

} </script>

代码清单 5-43兼容 IE 和 firefox 的 event 对象

<input type="button" value="click me" id="btn" /> <script type="text/JavaScript">

var btn = document.getElementById("btn");

btn.onclick = function(e){ e = window.event || e;

//下面可以用 e 来做点什么事,e 在 IE 和 Firefox 下都指向了 event 对象 }

</script>

代码清单 5-44兼容 srcElement 和 target

<input type="button" value="click me" id="btn" /> <span id="span">hello world</span>

<script type="text/JavaScript"> document.getElementById("btn").onclick = function(e){

e = window.event || e;

var el = e.srcElement || e.target;

alert(el.tagName);

} document.getElementById("span").onclick = function(e){

e = window.event || e;

var el = e.srcElement || e.target;

alert(el.tagName);

} </script>

代码清单 5-45封装 getEventTarget 函数

<input type="button" value="click me" /> <span id="span">hello world</span>

<script type="text/JavaScript"> function getEventTarget(e){

e = window.event || e;

return e.srcElement || e.target;

} document.getElementById("wrapper").onclick = function(e){

var node = getEventTarget(e);

alert(node.tagName);

} document.getElementById("span").onclick = function(e){

var node = getEventTarget(e);

alert(node.tagName);

} </script>

代码清单 5-46event 对象的冒泡

<style type="text/CSS"> #infoBox{padding:5px;border:2px dashed

#ccc;margin-bottom:10px;width:136px;height:20px;line-height:20px;text-align:center;

} #wrapper{padding:20px 0;background:black;width:150px;text-align:center;}

</style> <p id="infoBox"></p>

<script type="text/JavaScript"> var infoBox = document.getElementById("infoBox") , wrapper =

document.getElementById("wrapper") , btn = document.getElementById("btn");

wrapper.onclick = function(){ infoBox.innerHTML = "你点击的是:div";

} btn.onclick = function(){

infoBox.innerHTML = "你点击的是:input";

} </script>

代码清单 5-47监测冒泡的过程

<style type="text/CSS"> #infoBox{padding:5px;border:2px dashed

#ccc;margin-bottom:10px;width:136px;height:20px;line-height:20px;text-align:center;

} #wrapper{padding:20px 0;background:black;width:150px;text-align:center;}

</style> <p id="infoBox"></p>

<div id="wrapper"> <input type="button" value="click me" id="btn" />

</div> <script type="text/JavaScript">

var infoBox = document.getElementById("infoBox") , wrapper = document.getElementById("wrapper") , btn = document.getElementById("btn");

wrapper.onclick = function(){ infoBox.innerHTML = "你点击的是:div";

alert(1);

} btn.onclick = function(){

infoBox.innerHTML = "你点击的是:input";

alert(2);

} </script>

代码清单 5-48阻止事件冒泡

<style type="text/CSS"> #infoBox{padding:5px;border:2px dashed

#ccc;margin-bottom:10px;width:136px;height:20px;line-height:20px;text-align:center;

} #wrapper{padding:20px 0;background:black;width:150px;text-align:center;}

</style> <p id="infoBox"></p>

<div id="wrapper"> <input type="button" value="click me" id="btn" />

</div> <script type="text/JavaScript">

var infoBox = document.getElementById("infoBox") , wrapper = document.getElementById("wrapper") , btn = document.getElementById("btn");

wrapper.onclick = function(){ infoBox.innerHTML = "你点击的是:div";

} btn.onclick = function(e){

infoBox.innerHTML = "你点击的是:input";

e = window.event || e;

if(document.all){ e.cancelBubble=true;

} </script>

代码清单 5-49封装 stopPropagation 函数

<style type="text/CSS"> #infoBox{padding:5px;border:2px dashed

#ccc;margin-bottom:10px;width:136px;height:20px;line-height:20px;text-align:center;

} #wrapper{padding:20px 0;background:black;width:150px;text-align:center;}

</style> <p id="infoBox"></p>

<div id="wrapper"> <input type="button" value="click me" id="btn" />

</div> <script type="text/JavaScript">

function stopPropagation(e){ e = window.event || e;

if(document.all){ e.cancelBubble=true;

} else { e.stopPropagation();

} }

var infoBox = document.getElementById("infoBox") , wrapper = document.getElementById("wrapper") , btn = document.getElementById("btn");

wrapper.onclick = function(){ infoBox.innerHTML = "你点击的是:div";

} btn.onclick = function(e){

infoBox.innerHTML = "你点击的是:input";

stopPropagation(e);

} </script>

代码清单 5-50监听 click 事件

<input type="button" value="click me" id="btn" /> <script type="text/JavaScript">

var btn = document.getElementById("btn");

btn.onclick = function(){ alert(1);

} </script>

代码清单 5-51监听两个 click 事件

<input type="button" value="click me" id="btn" /> <script type="text/JavaScript">

var btn = document.getElementById("btn");

btn.onclick = function(){ alert(1);

} btn.onclick = function(){

alert(2);

} </script>

代码清单 5-52on xxx 在多人合作时的冲突问题

// 功能 A,made by 工程师甲 //===========================

(function(){ …

var btn = document.getElementById("btn");

btn.onclick = function(){ alert(1);

} …

})();

//========================== // 功能 B,made by 工程师乙

//=========================== (function(){

… var btn = document.getElementById("btn");

btn.onclick = function(){ alert(2);

} …

})();

</script>

代码清单 5-53使用 attachEvent 和 addEventListener 代替 on xxx

<input type="button" value="click me" id="btn" /> <script type="text/JavaScript">

var btn = document.getElementById("btn");

if(document.all){ btn.attachEvent("onclick",function(){

alert(1);

});

} else { btn.addEventListener("click",function(){

alert(1);

},false);

} if(document.all){

btn.attachEvent("onclick",function(){ alert(2);

});

} else { btn.addEventListener("click",function(){

alert(2);

},false);

} </script>

代码清单 5-54封装 on 函数

<input type="button" value="click me" id="btn" /> <script type="text/JavaScript">

function on(node,eventType,handler){ node = typeof node == "string" ? document.getElementById(node) : node;

if(document.all){ node.attachEvent("on"+eventType,handler);

} else { node.addEventListener(eventType,handler,false);

}

alert(1);

});

on(btn,"click",function(){ alert(2);

})

</script>

代码清单 5-55定义 trim函数

function trim(ostr){ return ostr.replace(/^\s+|\s+$/g,"");

} var str = " abc ";

alert(trim(str).length);// 3
alert(" "=="");// false
alert(trim(" ") == "");// true
代码清单5-56 定义类型判断函数

function isNumber(s){ return !isNaN(s);

} function isString(s){

return typeof s == "string";

} function isBoolean(s){

return typeof s == "boolean";

} function isFunction(s){

return typeof s == "function";

} function isNull(s){

return s == null;

} function isUndefined(s){

return typeof s == "undefined";

} function isEmpty(s){

return /^\s*$/.test(s);

} function isArray(s){

return s instanceof Array;

}

代码清单 5-57定义 get 和$函数

function get(node){ node = typeof node == "string" ? document.getElementById(node) : node;

return node;

} function $(node){

node = typeof node == "string" ? document.getElementById(node) : node;

return node;

} alert(get("test1").innerHTML);// Hello

alert($("test2").innerHTML)// World

代码清单 5-58定义 getElementsByClassName 函数

<span class="a">1</span>

<strong class="b">5</strong> <div id="wrapper"><strong class="b">6</strong></div>

<script type="text/JavaScript"> function getElementsByClassName(str,root,tag){

if(root){ root = typeof root == "string" ? document.getElementById(root) : root;

} else { root = document.body;

} tag = tag || "*";

var els = root.getElementsByTagName(tag),arr = [];

for(var i=0,n=els.length;i<n;i++){ for(var j=0,k=els[i].className.split(" "),l=k.length;j<l;j++){

if(k[j] == str){ arr.push(els[i]);

break;

} }

} return arr;

} var aEls = getElementsByClassName("a") , bEls =

getElementsByClassName("b","wrapper") , bEls2 = getElementsByClassName("b",null,"strong");

alert(aEls.length);// 3(1,2,3)
alert(bEls.length);// 1(6)
alert(bEls2.length);// 2(5,6)
代码清单5-59 定义extend函数

function extend(subClass,superClass){ var F = function(){};

F.prototype = superClass.prototype;

subClass.prototype = new F();

subClass.prototype.constructor = subClass;

subClass.superclass = superClass.prototype;

if(superClass.prototype.constructor == Object.prototype.constructor){ superClass.prototype.constructor = superClass;

} }

function Animal(name){ this.name = name;

this.type = "animal"

} Animal.prototype = {

say : function(){ alert("I'm a(an) " + this.type + " , my name is " + this.name);

} }

function Bird(name){ this.constructor.superclass.constructor.apply(this,arguments);

this.type = "bird"

} extend(Bird,Animal);

Bird.prototype.fly = function(){ alert("I'm flying");

canary.fly();// I’m flying

代码清单 5-60使用命名空间

var GLOBAL = {};

GLOBAL.namespace = function(str){ var arr = str.split("."),o = GLOBAL;

for (i=(arr[0] == "GLOBAL") ? 1 : 0; i<arr.length; i++) { o[arr[i]]=o[arr[i]] || {};

o=o[arr[i]];

} }

//Dom 相关 GLOBAL.namespace("Dom");

GLOBAL.Dom.getNextNode = function(node){ node = typeof node == "string" ? document.getElementById(node) : node;

var nextNode = node.nextSibling;

if(!nextNode) return null;

if(!document.all){ while(true){

if(nextNode.nodeType == 1){ break;

} else { if(nextNode.nextSibling){

nextNode = nextNode.nextSibling;

} else { break;

} }

} }

return nextNode;

};

GLOBAL.Dom.setOpacity = function(node, level){ node = typeof node == "string" ? document.getElementById(node) : node;

if (document.all){ node.style.filter = 'alpha(opacity=' + level + ')';

} else { node.style.opacity = level / 100;

} }

GLOBAL.Dom.get = function(node){ node = typeof node == "string" ? document.getElementById(node) : node;

return node;

} GLOBAL.Dom.getElementsByClassName = function(str,root,tag){

if(root){ root = typeof root == "string" ? document.getElementById(root) : root;

} else { root = document.body;

} tag = tag || "*";

var els = root.getElementsByTagName(tag),arr = [];

for(var i=0,n=els.length;i<n;i++){ for(var j=0,k=els[i].className.split(" "),l=k.length;j<l;j++){

if(k[j] == str){ arr.push(els[i]);

} return arr;

}

//Event 相关 GLOBAL.namespace("Event");

GLOBAL.Eevent.getEventTarget = function(e){ e = window.event || e;

return e.srcElement || e.target;

} GLOBAL.Event.stopPropagation = function(e){

e = window.event || e;

if(document.all){ e.cancelBubble=true;

} else { e.stopPropagation();

} }

GLOBAL.Event.on = function(node,eventType,handler){ node = typeof node == "string" ? document.getElementById(node) : node;

if(document.all){ node.attachEvent("on"+eventType,handler);

} else { node.addEventListener(eventType,handler,false);

} }

//Lang 相关 GLOBAL.namespace("Lang");

GLOBAL.Lang.trim = function(ostr){ return ostr.replace(/^\s+|\s+$/g,"");

} GLOBAL.Lang.isNumber = function(s){

return !isNaN(s);

} GLOBAL.Lang.extend = function(subClass,superClass){

var F = function(){};

F.prototype = superClass.prototype;

subClass.prototype = new F();

subClass.prototype.constructor = subClass;

subClass.superclass = superClass.prototype;

if(superClass.prototype.constructor == Object.prototype.constructor){ superClass.prototype.constructor = superClass;

} }

代码清单 5-61引入 common.js

<script type="text/JavaScript" src="base.js"></script> <script type="text/JavaScript" src="common.js"></script>

代码清单 5-62设置 cookie

document.cookie = "cookieName = cookieValue; expirationdate = timeValue; path = pathValue";

代码清单 5-63读写 cookie

// 设置 cookie

GMT; path=/";

/* 读取 cookie ** 此时 cookie 里的值为"name=adang; sex=male; blog=http://www.adanghome.com"

*/ var cookieStr = document.cookie;

// 对字符进行操作,取出 name 对应的值 var name = cookieStr.split("name")[1].split(";")[0].split("=")[1];

代码清单 5-64封装 cookie 组件

GLOBAL.namespace("Cookie");

GLOBAL.Cookie={ // 读取

read : function(name){ var cookieStr = "; "+document.cookie+"; ";

var index = cookieStr.indexOf("; "+name+"=");

if (index!=-1){ var s = cookieStr.substring(index+name.length+3,cookieStr.length);

return unescape(s.substring(0, s.indexOf("; ")));

}else{ return null;

} },

// 设置 set : function(name,value,expires){

var expDays = expires*24*60*60*1000;

var expDate = new Date();

expDate.setTime(expDate.getTime()+expDays);

var expString = expires ? "; expires="+expDate.toGMTString() : "";

var pathString = ";path=/";

document.cookie = name + "=" + escape(value) + expString + pathString;

}, // 删除

del : function(name){ var exp = new Date(new Date().getTime()-1);

var s=this.read(name);

if(s!=null) {document.cookie= name + "="+s+";expires="+exp.toGMTString()+";path=/"};

} };

代码清单 5-65引用可拖拽的 Msg 组件

<script type="text/JavaScript" src="base.js"></script> <script type="text/JavaScript" src="common_drag.js"></script>

<script type="text/JavaScript" src="common_msg.js"></script>

5.2.4page 层

5.2.5JavaScript 库

5.3编程实用技巧

5.3.1弹性

代码清单 5-66开始编写 Tab 组件

.tab-menuWrapper li{float:left;display:inline;padding:5px;border:1px solid #333;border-bottom:none;margin-right:5px;}

.tab-contentWrapper{border:1px solid #333;clear:left;padding:5px;} </style>

<div class="tab"> <ul class="tab-menuWrapper">

<li>menu1</li> <li>menu2</li>

<li>menu3</li> </ul>

<div class="tab-contentWrapper"> <div>content1</div>

<div style="display:none">content2</div> <div style="display:none">content3</div>

</div> </div>

代码清单 5-67给 html 标签挂上 id

… <div class="tab">

<ul class="tab-menuWrapper"> <li id="tab-menu1">menu1</li>

<li id="tab-menu2">menu2</li> <li id="tab-menu3">menu3</li>

</ul> <div class="tab-contentWrapper">

<div id="tab-content1">content1</div> <div id="tab-content2" style="display:none">content2</div>

<div id="tab-content3" style="display:none">content3</div> </div>

</div> <script type="text/JavaScript">

//获得 tabMenu 和 tabContent 的 DOM 节点,并保存在变量中 var tabMenu1 = document.getElementById("tab-menu1") ,

tabMenu2 = document.getElementById("tab-menu2") , tabMenu3 = document.getElementById("tab-menu3") ,

tabContent1 = document.getElementById("tab-content1") , tabContent2 = document.getElementById("tab-content2") ,

tabContent3 = document.getElementById("tab-content3");

//让 tabMenu 监听点击 click 事件 tabMenu1.onclick = function(){

//显示 tabContent1,隐藏 tabContent2 和 tabContent3 tabContent1.style.display = "block";

tabContent2.style.display = "none";

tabContent3.style.display = "none";

} tabMenu2.onclick = function(){

//显示 tabContent2,隐藏 tabContent1 和 tabContent3 tabContent1.style.display = "none";

tabContent2.style.display = "block";

tabContent3.style.display = "none";

} tabMenu3.onclick = function(){

//显示 tabContent3,隐藏 tabContent1 和 tabContent2 tabContent1.style.display = "none";

tabContent2.style.display = "none";

代码清单 5-68提高 Tab 的扩展性

… <div class="tab">

<ul class="tab-menuWrapper" id="tab-menuWrapper"> <li>menu1</li>

<li>menu2</li> <li>menu3</li>

<li>menu4</li> </ul>

<div class="tab-contentWrapper" id="tab-contentWrapper"> <div>content1</div>

<div style="display:none">content2</div> <div style="display:none">content3</div>

<div style="display:none">content4</div> </div>

</div> <script type="text/JavaScript">

//获得 tabMenu 和 tabContent 的节点,并以数组的形式保存在变量中 var tabMenus =

document.getElementById("tab-menuWrapper").getElementsByTagName("li") , tabContents =

document.getElementById("tab-contentWrapper").getElementsByTagName("div");

//遍历数组,让 tabMenu 监听 click 事件 for(var i=0;i<tabMenus.length;i++){

tabMenus[i].onclick = function(){ //遍历数组,隐藏所有 tabContent

for(var j=0;j<tabContents.length;j++){ tabContents[j].style.display = "none";

} //显示被点击的 tabMenu 对应的 tabContent

tabContents[i].style.display = "block";

} }

</script>

代码清单 5-69循环中的 i

for(var i=0;i<tabMenus.length;i++){ tabMenus[i].onclick = function(){

//弹出当前索引 alert(i);

//遍历数组,隐藏所有 tabContent for(var j=0;j<tabContents.length;j++){

tabContents[j].style.display = "none";

} //显示被点击的 tabMenu 对应的 tabContent

tabContents[i].style.display = "block";

} }

代码清单 5-70解决循环 bug 方法一

for(var i=0;i<tabMenus.length;i++){ (function(_i){

tabMenus[_i].onclick = function(){ for(var j=0;j<tabContents.length;j++){

tabContents[j].style.display = "none";

})(i);

}

代码清单 5-71解决循环 bug 方法二

for(var i=0;i<tabMenus.length;i++){ tabMenus[i]._index = i;

tabMenus[i].onclick = function(){ for(var j=0;j<tabContents.length;j++){

tabContents[j].style.display = "none";

} tabContents[this._index].style.display = "block";

} }

代码清单 5-72两个标签的 Tab

<!—- 两个标签 --> <div class="tab">

<ul class="tab-menuWrapper" id="tab-menuWrapper"> <li>menu1</li>

<li>menu2</li> </ul>

<div class="tab-contentWrapper" id="tab-contentWrapper"> <div>content1</div>

<div style="display:none">content2</div> </div>

</div>

代码清单 5-73五个标签的 Tab

<!—- 五个标签 --> <div class="tab">

<ul class="tab-menuWrapper" id="tab-menuWrapper"> <li>menu1</li>

<li>menu2</li> <li>menu3</li>

<li>menu4</li> <li>menu5</li>

</ul> <div class="tab-contentWrapper" id="tab-contentWrapper">

<div>content1</div> <div style="display:none">content2</div>

<div style="display:none">content3</div> <div style="display:none">content4</div>

<div style="display:none">content5</div> </div>

</div>

代码清单 5-74结构稍复杂的 Tab

<div class="tab"> <ul class="tab-menuWrapper" id="tab-menuWrapper">

<li>menu1</li> <li>menu2</li>

<li>menu3</li> </ul>

<div class="tab-contentWrapper" id="tab-contentWrapper"> <div><div>content1</div><ul><li>abc</li></ul></div>

<div style="display:none"><p>content2</p><div>abc</div></div>

代码清单 5-75复杂 Tab 结构带来的问题

<div class="tab"> <ul class="tab-menuWrapper" id="tab-menuWrapper">

<li>menu1</li> <li>menu2</li>

<li>menu3</li> </ul>

<div class="tab-contentWrapper" id="tab-contentWrapper"> <div><div>content1</div><ul><li>abc</li></ul></div>

<div style="display:none"><p>content2</p><div>abc</div></div> <div style="display:none">content3</div>

</div> </div>

<script type="text/JavaScript"> var tabMenus =

document.getElementById("tab-menuWrapper").getElementsByTagName("li") , tabContents =

document.getElementById("tab-contentWrapper").getElementsByTagName("div");

alert(tabContents.length);

//弹出 5,不是 3 …

5.3.2getElementById、getElementsByTagName和

getElementsByClassName

代码清单 5-76使用 getElementsByClassName

… <div class="tab">

<ul class="tab-menuWrapper" id="tab-menuWrapper"> <li>menu1</li>

<li>menu2</li> <li>menu3</li>

</ul> <div class="tab-contentWrapper">

<div class="J_tab-content"><div>content1</div><ul>abc</ul></div> <div class="J_tab-content"

style="display:none"><p>content2</p><div>abc</div></div> <div class="J_tab-content" style="display:none">content3</div>

</div> </div>

<script type="text/JavaScript"> var GLOBAL = {};

GLOBAL.namespace = function(str){ var arr = str.split("."),o = GLOBAL;

for (i=(arr[0] == "GLOBAL") ? 1 : 0; i<arr.length; i++) { o[arr[i]]=o[arr[i]] || {};

o=o[arr[i]];

} }

GLOBAL.namespace("Dom");

GLOBAL.Dom.getElementsByClassName = function(str,root,tag){ if(root){

root = typeof root == "string" ?

document.getElementById(root) : root;

} else {

var els = root.getElementsByTagName(tag),arr = [];

for(var i=0,n=els.length;i<n;i++){ for(var j=0,k=els[i].className.split("

"),l=k.length;j<l;j++){ if(k[j] == str){

arr.push(els[i]);

break;

} }

} return arr;

}

var tabMenus = document.getElementById("tab-menuWrapper").getElementsByTagName("li"),

tabContents = GLOBAL.Dom.getElementsByClassName("J_tab-content");

for(var i=0;i<tabMenus.length;i++){ tabMenus[i]._index = i;

tabMenus[i].onclick = function(){ for(var j=0;j<tabContents.length;j++){

tabContents[j].style.display = "none";

} tabContents[this._index].style.display = "block";

} }

</script>

5.3.3可复用性

代码清单 5-77将 id 换为 class

… <div class="tab">

<ul class="tab-menuWrapper"> <li class="J_tab-menu">menu1</li>

<li class="J_tab-menu">menu2</li> <li class="J_tab-menu">menu3</li>

</ul> …

var tabMenus = GLOBAL.Dom.getElementsByClassName("J_tab-menu");

…

代码清单 5-78三个 Tab

<div class="tab"> <ul class="tab-menuWrapper">

<li class="J_tab-menu">menu1-1</li> <li class="J_tab-menu">menu1-2</li>

<li class="J_tab-menu">menu1-3</li> </ul>

<div class="tab-contentWrapper"> <div class="J_tab-content"><div>content1-1</div><ul>abc</ul></div>

<div class="J_tab-content"

style="display:none"><p>content1-2</p><div>abc</div></div> <div class="J_tab-content" style="display:none">content1-3</div>

</div> </div>

<li class="J_tab-menu">menu2-2</li> </ul>

<div class="tab-contentWrapper"> <div class="J_tab-content"><div>content2-1</div><ul>abc</ul></div>

<div class="J_tab-content"

style="display:none"><p>content2-2</p><div>abc</div></div> </div>

</div> <div class="tab">

<ul class="tab-menuWrapper"> <li class="J_tab-menu">menu3-1</li>

<li class="J_tab-menu">menu3-2</li> <li class="J_tab-menu">menu3-3</li>

<li class="J_tab-menu">menu3-4</li> <li class="J_tab-menu">menu3-5</li>

</ul> <div class="tab-contentWrapper">

<div class="J_tab-content"><div>content3-1</div><ul>abc</ul></div> <div class="J_tab-content"

style="display:none"><p>content3-2</p><div>abc</div></div> <div class="J_tab-content" style="display:none">content3-3</div>

<div class="J_tab-content"

style="display:none"><p>content3-4</p><div>abc</div></div> <div class="J_tab-content" style="display:none">content3-5</div>

</div> </div>

代码清单 5-79给 Tab 添加根结点挂钩

… <div class="tab J_tab">

<ul class="tab-menuWrapper"> …

</ul> <div class="tab-contentWrapper">

… </div>

</div> <div class="tab J_tab">

<ul class="tab-menuWrapper"> …

</ul> <div class="tab-contentWrapper">

… </div>

</div> <div class="tab J_tab">

<ul class="tab-menuWrapper"> …

</ul> <div class="tab-contentWrapper">

… </div>

</div> <script type="text/JavaScript">

…

function setTab(root){

tabMenus[i]._index = i;

tabMenus[i].onclick = function(){ for(var j=0;j<tabContents.length;j++){

tabContents[j].style.display = "none";

} tabContents[this._index].style.display = "block";

} }

}

var tabs = GLOBAL.Dom.getElementsByClassName("J_tab");

for(var i=0;i<tabs.length;i++){ setTab(tabs[i]);

} </script>

5.3.4避免产生副作用

代码清单 5-80高亮当前 Tab

<style type="text/CSS"> …

.tab .tab-currentMenu{background-color:#333;color:#fff;} </style>

<div class="tab J_tab"> <ul class="tab-menuWrapper">

<li class="J_tab-menu .tab-currentMenu">menu1-1</li> <li class="J_tab-menu">menu1-2</li>

<li class="J_tab-menu">menu1-3</li> </ul>

<div class="tab-contentWrapper"> …

</div> </div>

<div class="tab J_tab"> <ul class="tab-menuWrapper">

<li class="J_tab-menu .tab-currentMenu">menu2-1</li> <li class="J_tab-menu">menu2-2</li>

</ul> <div class="tab-contentWrapper">

… </div>

</div> <div class="tab J_tab">

<ul class="tab-menuWrapper"> <li class="J_tab-menu .tab-currentMenu">menu3-1</li>

<li class="J_tab-menu">menu3-2</li> <li class="J_tab-menu">menu3-3</li>

<li class="J_tab-menu">menu3-4</li> <li class="J_tab-menu">menu3-5</li>

</ul> <div class="tab-contentWrapper">

… </div>

</div> <script type="text/JavaScript">

…

for(var i=0;i<tabMenus.length;i++){ tabMenus[i]._index = i;

tabMenus[i].onclick = function(){ for(var j=0;j<tabContents.length;j++){

tabContents[j].style.display = "none";

} tabContents[this._index].style.display = "block";

//如果有当前选中标签,则去掉“tab-currentMenu”

var currentMenu = GLOBAL.Dom.getElementsByClassName("tab-currentMenu",root)[0];

if(currentMenu){ currentMenu.className = "";

} //给当前被点击的按钮挂上当前选中的 class

this.className = "tab-currentMenu";

} }

} …

</script>

代码清单 5-81修改 className

if(currentMenu){ currentMenu.className = "";

} this.className = "tab-currentMenu";

代码清单 5-82修改 className 引起的冲突

<style type="text/CSS"> …

.tab .tab-currentMenu{background-color:#333;color:#fff;} .underLine{text-decoration:underline;}

</style> …

<div class="tab"> <ul class="tab-menuWrapper">

<li class="J_tab-menu">menu1-1</li> <li class="J_tab-menu">menu1-2</li>

<li class="J_tab-menu underLine">menu1-3</li> </ul>

…

代码清单 5-83修改至无副作用

if(currentMenu){ currentMenu.className = currentMenu.className.replace(new

RegExp("(^|\\s+)tab-currentMenu"),"");

} if(!new RegExp("(^|\\s+)tab-currentMenu").test(this.className)){

this.className =this.className + " tab-currentMenu";

}

代码清单 5-84定义 addClass 和 removeClass 函数

… GLOBAL.Dom.addClass = function(node,str){

if(!new RegExp("(^|\\s+)"+str).test(node.className)){ node.className = node.className + " " + str;

node.className = node.className.replace(new RegExp("(^|\\s+)"+str),"");

} …

if(currentMenu){ GLOBAL.Dom.removeClass(currentMenu,"tab-currentMenu");

} GLOBAL.Dom.addClass(this,"tab-currentMenu");

…

5.3.5通过传参实现定制

代码清单 5-85编写 setTab、setTab2 和 setTab3

<style type="text/CSS"> …

.tab .tab-currentMenu{background-color:#333;color:#fff;} .tab .tab-currentMenu2{background-color:blue;color:#fff;}

.underLine{text-decoration:underline;} </style>

<div class="tab J_tab"> <ul class="tab-menuWrapper">

<li class="J_tab-menu">menu1-1</li> <li class="J_tab-menu">menu1-2</li>

<li class="J_tab-menu">menu1-3</li> </ul>

<div class="tab-contentWrapper"> …

</div> </div>

<div class="tab J_tab"> <ul class="tab-menuWrapper">

<li class="J_tab-menu .tab-currentMenu">menu2-1</li> <li class="J_tab-menu">menu2-2</li>

</ul> <div class="tab-contentWrapper">

… </div>

</div> <div class="tab J_tab">

<ul class="tab-menuWrapper"> <li class="J_tab-menu .tab-currentMenu2">menu3-1</li>

<li class="J_tab-menu">menu3-2</li> <li class="J_tab-menu">menu3-3</li>

<li class="J_tab-menu">menu3-4</li> <li class="J_tab-menu">menu3-5</li>

</ul> <div class="tab-contentWrapper">

… </div>

</div> <script type="text/JavaScript">

… function setTab(root){

… //去掉高亮当前标签的功能

/* var currentMenu =

} GLOBAL.Dom.addClass(this,"tab-currentMenu");

*/ …

} function setTab2(root){

… //当前标签挂上高亮样式 1

var currentMenu = GLOBAL.Dom.getElementsByClassName("tab-currentMenu",root)[0];

if(currentMenu){ GLOBAL.Dom.removeClass(currentMenu,"tab-currentMenu");

} GLOBAL.Dom.addClass(this,"tab-currentMenu");

… }

function setTab3(root){ …

//当前标签挂上高亮样式 2 var currentMenu =

GLOBAL.Dom.getElementsByClassName("tab-currentMenu2",root)[0];

if(currentMenu){ GLOBAL.Dom.removeClass(currentMenu,"tab-currentMenu2");

} GLOBAL.Dom.addClass(this,"tab-currentMenu2");

… }

var tabs = GLOBAL.Dom.getElementsByClassName("J_tab");

setTab(tabs[0]);

setTab2(tabs[1]);

setTab3(tabs[2]);

</script>

代码清单 5-86用参数写活变化的部分

function setTab(root,currentClass){ …

if(currentClass){ var currentMenu = GLOBAL.Dom.getElementsByClassName(currentClass,root)[0];

if(currentMenu){ GLOBAL.Dom.removeClass(currentMenu,currentClass);

} GLOBAL.Dom.addClass(this,currentClass);

} …

}

var tabs = GLOBAL.Dom.getElementsByClassName("J_tab");

setTab(tabs[0]);

setTab(tabs[1],"tab-currentMenu");

setTab(tabs[2],"tab-currentMenu2");

</script>

代码清单 5-87写活事件触发方式

… GLOBAL.namespace("Event");

GLOBAL.Event.on = function(node,eventType,handler){

} else { node.addEventListener(eventType,handler,false);

} }

… function setTab(root,currentClass,trigger){

var tabMenus = GLOBAL.Dom.getElementsByClassName("J_tab-menu",root), tabContents = GLOBAL.Dom.getElementsByClassName("J_tab-content",root);

//如果不传入激活类型,默认激活类型为点击 trigger = trigger || "click";

for(var i=0;i<tabMenus.length;i++){ tabMenus[i]._index = i;

//调用 base 层提供的 on 方法 GLOBAL.Event.on(tabMenus[i],trigger,function(){

for(var j=0;j<tabContents.length;j++){ tabContents[j].style.display = "none";

} tabContents[this._index].style.display = "block";

if(currentClass){ var currentMenu =

GLOBAL.Dom.getElementsByClassName(currentClass,root)[0];

if(currentMenu){ GLOBAL.Dom.removeClass(currentMenu,currentClass);

} GLOBAL.Dom.addClass(this,currentClass);

} });

} }

var tabs = GLOBAL.Dom.getElementsByClassName("J_tab");

//将 Tab1 和 Tab3 的标签激活方式改为 mouseover setTab(tabs[0],null,"mouseover");

setTab(tabs[1],"tab-currentMenu");

setTab(tabs[2],"tab-currentMenu2","mouseover");

</script>

5.3.6控制 this 关键字的指向

代码清单 5-88调试 bug

… GLOBAL.Event.on(tabMenus[i],trigger,function(){

for(var j=0;j<tabContents.length;j++){ tabContents[j].style.display = "none";

} alert(this._index);

tabContents[this._index].style.display = "block";

代码清单 5-89javascript 伪协议和内联事件

// 弹出“A”

<a href="#" onclick="alert(this.tagName)">click me</a> // 弹出“undefined”

<a href="JavaScript:alert(this.tagName)">click me</a> // 弹出“true”

<a href="JavaScript:alert(this == window)">click me</a>

代码清单 5-90setTimeout 和 setInterval 改变 this 指向

say : function(){ alert("I'm " + this.name);

} };

adang.say();// I’m adang
setTimeout(adang.say,1000);// I’m someBody
setInterval(adang.say,1000);// I’m someBody
代码清单5-91 onxxx改变this指向

<input type="button" value="click me" id="btn" name="BUTTON" />

var name = "somebody";

var btn = document.getElementById("btn");

var adang = { name : "adang",

say : function(){ alert("I'm " + this.name);

} };

btn.onclick = adang.say;// I’m BUTTON

代码清单 5-92匿名函数调整 this 指向

<input type="button" value="click me" id="btn" name="BUTTON" />

var name = "somebody";

var btn = document.getElementById("btn");

var adang = { name : "adang",

say : function(){ alert("I'm " + this.name);

} };

adang.say();// I’m adang
setTimeout(function(){adang.say()},1000);// I’m adang
setInterval(function(){adang.say()},1000);// I’m adang
btn.onclick = function(){adang.say()};// I’m adang
setTimeout(function(){alert(this == window)},1000);// true
btn.onclick = function(){alert(this == btn)};// true
代码清单5-93 call和apply调整this指向

<input type="button" value="click me" id="btn" name="BUTTON" />

var name = "somebody";

var btn = document.getElementById("btn");

var adang = { name : "adang",

say : function(){ alert("I'm " + this.name);

} };

adang.say.call(btn);// I’m BUTTON
setTimeout(function(){adang.say.call(btn)},1000);// I’m BUTTON
setInterval(function(){adang.say.apply(btn)},1000);// I’m BUTTON
btn.onclick = function(){adang.say.apply(btn)};// I’m BUTTON
代码清单5-94 将this指向的对象保存到变量

var adang = { name : "adang",

say : function(){ alert("I'm " + this.name);

}, init : function(){

// this 指向 adang 对象 var This = this;

document.getElementById("btn").onclick = function(){ // this 指向 btn 的 Dom 节点,This 指向 adang 对象

This.say();// I’m adang this.say();// 报错,this.say is not a function

};

} };

adang.init();

代码清单 5-95调试 bug

… GLOBAL.Event.on(tabMenus[i],trigger,function(){

for(var j=0;j<tabContents.length;j++){ tabContents[j].style.display = "none";

} alert(this == window);

tabContents[this._index].style.display = "block";

代码清单 5-96attachEvent、addEventListener 和 this 指针

<input type="button" value="click me" id="btn" /> <script type="text/JavaScript">

var btn = document.getElementById("btn");

if(document.all){ // ie

btn.attachEvent("onclick",function(){ alert(this.tagName);//undefined

alert(this == window);//true });

} else { // Firefox

btn.addEventListener("click",function(){ alert(this.tagName);//INPUT

alert(this == window);//false },false);

} </script>

代码清单 5-97加强 on 函数的功能

GLOBAL.Event.on = function(node,eventType,handler,scope){ node = typeof node == "string" ? document.getElementById(node) : node;

scope = scope || node;

if(document.all){ node.attachEvent("on"+eventType,function(){handler.apply(scope,arguments)})

;

} else { node.addEventListener(eventType,function(){handler.apply(scope,arguments)},

false);

5.3.7预留回调接口

代码清单 5-98设置回调函数

… function setTab(root,currentClass,trigger,handler){

var tabMenus = GLOBAL.Dom.getElementsByClassName("J_tab-menu",root), tabContents = GLOBAL.Dom.getElementsByClassName("J_tab-content",root);

trigger = trigger || "click";

for(var i=0;i<tabMenus.length;i++){ tabMenus[i]._index = i;

GLOBAL.Event.on(tabMenus[i],trigger,function(){ for(var j=0;j<tabContents.length;j++){

tabContents[j].style.display = "none";

} tabContents[this._index].style.display = "block";

if(currentClass){ var currentMenu =

GLOBAL.Dom.getElementsByClassName(currentClass,root)[0];

if(currentMenu){ GLOBAL.Dom.removeClass(currentMenu,currentClass);

} GLOBAL.Dom.addClass(this,currentClass);

} if(handler){

handler(this._index);

} });

} }

var tabs = GLOBAL.Dom.getElementsByClassName("J_tab");

setTab(tabs[0],null,"mouseover");

setTab(tabs[1],"tab-currentMenu");

setTab(tabs[2],"tab-currentMenu2","mouseover",function(index){alert("您激活的是第 "+(index+1)+"个标签")});

5.3.8don’t repeat yourself

代码清单 5-99添加自动切换功能

… function setTab(root,currentClass,trigger,handler,autoPlay,playTime){

var tabMenus = GLOBAL.Dom.getElementsByClassName("J_tab-menu",root), tabContents = GLOBAL.Dom.getElementsByClassName("J_tab-content",root);

trigger = trigger || "click";

playTime = playTime || 3000;

var currentIndex = 0;

function autoHandler(){ currentIndex++;

if(currentIndex >= tabMenus.length){ currentIndex = 0;

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

tabContents[i].style.display = "none";

} tabContents[currentIndex].style.display = "block";

if(currentMenu){ GLOBAL.Dom.removeClass(currentMenu,currentClass);

} GLOBAL.Dom.addClass(tabMenus[currentIndex],currentClass);

} if(handler){

handler(currentIndex);

} }

if(autoPlay){ setInterval(autoHandler,playTime);

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

tabMenus[i]._index = i;

GLOBAL.Event.on(tabMenus[i],trigger,function(){ for(var j=0;j<tabContents.length;j++){

tabContents[j].style.display = "none";

} tabContents[this._index].style.display = "block";

if(currentClass){ var currentMenu =

GLOBAL.Dom.getElementsByClassName(currentClass,root)[0];

if(currentMenu){ GLOBAL.Dom.removeClass(currentMenu,currentClass);

} GLOBAL.Dom.addClass(this,currentClass);

} if(handler){

handler(this._index);

} currentIndex = this._index;

});

} }

var tabs = GLOBAL.Dom.getElementsByClassName("J_tab");

setTab(tabs[0],null,"mouseover");

setTab(tabs[1],"tab-currentMenu",null,null,true,5000);

setTab(tabs[2],"tab-currentMenu2","mouseover",function(index){alert("您激活的是第 "+(index+1)+"个标签")});

代码清单 5-100重构代码,将相同代码提取出来

… function setTab(root,currentClass,trigger,handler,autoPlay,playTime){

var tabMenus = GLOBAL.Dom.getElementsByClassName("J_tab-menu",root), tabContents = GLOBAL.Dom.getElementsByClassName("J_tab-content",root);

trigger = trigger || "click";

playTime = playTime || 3000;

var currentIndex = 0;

function showItem(n){ for(var i=0;i<tabContents.length;i++){

tabContents[i].style.display = "none";

} tabContents[n].style.display = "block";

if(currentClass){ var currentMenu =

GLOBAL.Dom.getElementsByClassName(currentClass,root)[0];

} GLOBAL.Dom.addClass(tabMenus[n],currentClass);

} if(handler){

handler(n);

} }

function autoHandler(){ currentIndex++;

if(currentIndex >= tabMenus.length){ currentIndex = 0;

} showItem(currentIndex);

} if(autoPlay){

setInterval(autoHandler,playTime);

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

tabMenus[i]._index = i;

GLOBAL.Event.on(tabMenus[i],trigger,function(){ showItem(this._index);

currentIndex = this._index;

});

} }

var tabs = GLOBAL.Dom.getElementsByClassName("J_tab");

setTab(tabs[0],null,"mouseover");

setTab(tabs[1],"tab-currentMenu",null,null,true,5000);

setTab(tabs[2],"tab-currentMenu2","mouseover",function(index){alert("您激活的是第 "+(index+1)+"个标签")});

5.3.9用 hash 对象传参

代码清单 5-101普通方式传参和 hash 对象传参

// 普通方式传参 function test(a,b,c){

var oA = a || 1, oB = b || 2, oC = c || 3;

} test(4,5,6);

test(null,7,8);

test(null,null,9);

// 用 hash 对象传参 function test2(config){

var oA = config.a || 1, oB = config.b || 2, oC = config.c || 3;

} test2({a:4,b:5,c:6});

test2({b:7,c:8});

test2({c:9});

代码清单 5-102改用 hash 对象传参

… function setTab(config){

var root = config.root;

var currentClass = config.currentClass;

var playTime = config.playTime || 3000;

var tabMenus = GLOBAL.Dom.getElementsByClassName("J_tab-menu",root), tabContents = GLOBAL.Dom.getElementsByClassName("J_tab-content",root);

var currentIndex = 0;

function showItem(n){ for(var i=0;i<tabContents.length;i++){

tabContents[i].style.display = "none";

} tabContents[n].style.display = "block";

if(currentClass){ var currentMenu =

GLOBAL.Dom.getElementsByClassName(currentClass,root)[0];

if(currentMenu){ GLOBAL.Dom.removeClass(currentMenu,currentClass);

} GLOBAL.Dom.addClass(tabMenus[n],currentClass);

} if(handler){

handler(n);

} }

function autoHandler(){ currentIndex++;

if(currentIndex >= tabMenus.length){ currentIndex = 0;

} showItem(currentIndex);

} if(autoPlay){

setInterval(autoHandler,playTime);

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

tabMenus[i]._index = i;

GLOBAL.Event.on(tabMenus[i],trigger,function(){ showItem(this._index);

currentIndex = this._index;

});

} }

var tabs = GLOBAL.Dom.getElementsByClassName("J_tab");

setTab({root:tabs[0],trigger:"mouseover"});

setTab({root:tabs[1],currentClass:"tab-currentMenu",autoPlay:true,playTime:5000});

setTab({root:tabs[2],currentClass:"tab-currentMenu2",trigger:"mouseover",handler:fu nction(index){alert("您激活的是第"+(index+1)+"个标签")}});

5.4面向对象编程

5.4.1面向过程编程和面向对象编程

代码清单 5-103电话本程序

// 定义电话本 1 var phonebook = [

{name:"adang",tel:"111111"}, {name:"zhangxia",tel:"222222"},

];

// 定义电话本 2 var phonebook2 = [

{name:"niaoren",tel:"111111"}, {name:"j2ee",tel:"222222"},

{name:"baobao",tel:"333333"} ];

// 查询电话 function getTel(oPhonebook,oName){

var tel = "";

for(var i=0;i<oPhonebook.length;i++){ if(oPhonebook[i].name == oName){

tel = oPhonebook[i].tel;

break;

} }

return tel;

}

// 添加记录 function addItem(oPhonebook,oName,oTel){

oPhonebook.push({name:oName,tel:oTel});

}

// 删除记录 function removeItem(oPhonebook,oName){

var n;

for(var i=0;i<oPhonebook.length;i++){ if(oPhonebook[i].name == oName){

n = i;

break;

} }

if(n != undefined){ oPhonebook.splice(n,1);

} }

// 从电话本 1 中查询”niaoren”的电话 var str = getTel(phonebook,"niaoren");

alert(str);// ""

// 在电话本 1 中添加”niaoren”的记录 addItem(phonebook,"niaoren","666666");

str = getTel(phonebook,"niaoren");

alert(str);// "666666"

// 在电话本 1 中删除”niaoren”的记录 removeItem(phonebook,"niaoren");

str = getTel(phonebook,"niaoren");

alert(str);// ""

// 在电话本 2 中查询”niaoren”的记录 str = getTel(phonebook2,"niaoren");

alert(str);// "111111"

var say = function(oName){ alert("I'm " + oName);

} var sleep = function(oState){

oState = "asleep"

} say(name);

sleep(state);

代码清单 5-105面向对象方式编程

var adang = { name : "adang",

state : "awake", say : function(){

alert("I'm " + this.name);

}, sleep : function(){

this.state = "asleep";

} };

adang.say();

adang.sleep();

5.4.2JavaScript 的面向对象编程

代码清单 5-106java 的类

// 定义 Animal 类 public class Animal{

String name , type = "animal";

public Animal(String a) { name = a;

} public void say(){

System.out.println("I'm a(an) " + type + " , my name is " + name);

} }

...

// 实例化 Animal 类 Animal myDog = new Animal("wangcai");

myDog.say();

代码清单 5-107JavaScript 中的类

// 函数作为普通函数 function sayHi(){

alert("hi");

} // 调用函数

sayHi();

// 函数作为类 function Animal(name){

this.name = name;

this.type = "animal";

this.say = function(){ alert("I'm a(an) " + this.type + " , my name is " + this.name);

}

myDog.say();

代码清单 5-108构造函数和原型之间的引用

// 定义 Animal 类的构造函数 function Animal(){

… }

var a = Animal.prototype;// a指向Animal类对应的原型
var b = a.constructor;// b指向a对应的类的构造函数
alert(b == Animal)// true
代码清单5-109 使用原型

// 定义 Animal 类 function Animal(){

} // 修改 Animal 类的原型

Animal.prototype = { name : "xxx",

type : "animal", say : function(){

alert("I'm a(an) " + this.type + " , my name is " + this.name);

} }

// 实例化 Animal 类 var myDog = new Animal();

myDog.say();// I’m a(an) animal , my name is xxx

代码清单 5-110使用原型的另一种方法

// 修改 Animal 类的原型 Animal.prototype.name = "xxx";

Animal.prototype.type = "ANIMAL";

Animal.prototype.say = function(){ alert("I'm a(an) " + this.type + " , my name is " + this.name);

};

代码清单 5-111JavaScript 类的典型用法

// 定义 Animal 类 function Animal(name){

this.name = name || "xxx";

this.type = "animal";

} // 修改 Animal 类的原型

Animal.prototype = { say : function(){

alert("I'm a(an) " + this.type + " , my name is " + this.name);

} }

// 实例化 Animal 类 var myDog = new Animal("wangcai");

myDog.say();// I’m a(an) animal , my name is wangcai

代码清单 5-112JavaScript 中的公有和私有

// 定义 Animal 类 function Animal(name){

// 公有属性

var age = 20;

// 私有方法 var move = function(){

aler("I'm moving now");

} }

// 修改 Animal 类的原型 Animal.prototype = {

// 公有方法 say : function(){

alert("I'm a(an) " + this.type + " , my name is " + this.name);

} }

// 实例化 Animal 类 var myDog = new Animal("wangcai");

alert(myDog.name);// wangcai alert(myDog.age);// undefined

myDog.move();// 报错,myDog.move is not function

代码清单 5-113私有属性的作用域

// 定义 Animal 类 function Animal(name){

// 公有属性 this.name = name || "xxx";

this.type = "animal";

// 私有属性 var age = 20;

// 私有方法 var move = function(){

aler("I'm moving now");

} }

// 修改 Animal 类的原型 Animal.prototype = {

// 公有方法 say : function(){

alert("I'm a(an) " + this.type + " , my name is " + this.name + " , I'm " + age);

}, act : function(){

move();

} }

// 实例化 Animal 类 var myDog = new Animal("wangcai");

myDog.say();// 报错,age 未定义 myDog.act();// 报错,move is not defined

代码清单 5-114行为访问私有属性的方法

// 定义 Animal 类 function Animal(name){

// 公有属性 this.name = name || "xxx";

this.type = "animal";

// 私有属性 var age = 20;

// 私有方法

this.say = function(){ alert("I'm a(an) " + this.type + " , my name is " + this.name + " , I'm

" + age);

} this.act = function(){

move();

} }

// 修改 Animal 类的原型 Animal.prototype = {

} // 实例化 Animal 类

var myDog = new Animal("wangcai");

myDog.say();// I’m a(an) animal , my name is wangcai , I’m 20
myDog.act();// I’m moving now
代码清单5-115使用命名约定来模拟“私有”属性

// 定义 Animal 类 function Animal(name){

// 公有属性 this.name = name || "xxx";

this.type = "animal";

// 私有属性 this._age = 20;

} // 修改 Animal 类的原型

Animal.prototype = { // _开头,私有方法

_move : function(){ alert("I'm moving now");

}, // 公有方法

say : function(){ alert("I'm a(an) " + this.type + " , my name is " + this.name + " , I'm

" + this._age);

}, act : function(){

this._move();

} }

// 实例化 Animal 类 var myDog = new Animal("wangcai");

myDog.say();// I’m a(an) animal , my name is wangcai , I’m 20
myDog.act();// I’m moving now
myDog._move();// I’m moving now (不推荐实例直接调用_move,违反命名约定)
alert(myDog._age);// 20 (不推荐实例直接调用_age,违反命名约定)
代码清单5-116通过get和set方法访问属性

function Animal(name){ var name;

var type = "animal";

var _age = 20;

this.getName = function(){ return name;

} this.setName = function(o){

name = o;

} this.setType = function(o){

type = o;

} this._getAge = function(){

return _age;

} this._setAge = function(o){

_age = o;

} this.setName(name);

} Animal.prototype = {

_move : function(){ alert("I'm moving now");

}, say : function(){

alert("I'm a(an) " + this.getType() + " , my name is " + this.getName()

  • " , I'm " + this._getAge());

}, act : function(){

this._move();

} }

var myDog = new Animal("wangcai");

myDog.say();// I’m a(an) animal , my name is wangcai , I’m 20
myDog.setType("dog");//通过set方法设置type属性的值
alert(myDog.getType());//通过get方法获取type属性的值
代码清单5-117 通过set方法保护属性

function Animal(name){ var name;

var type = "animal";

var _age = 20;

this.getName = function(){ return name;

} this.setName = function(o){

if(o != "wangcai" && o != "xiaoqiang"){ alert("您设置的 name 值不合要求");

return;

} name = o;

} this.getType = function(){

return type;

} this.setType = function(o){

alert("赋值失败,Animal 类的 type 属性是只读的");

} this._getAge = function(){

return _age;

} this._setAge = function(o){

_age = o;

Animal.prototype = { _move : function(){

alert("I'm moving now");

}, say : function(){

alert("I'm a(an) " + this.getType() + " , my name is " + this.getName()

  • " , I'm " + this._getAge());

}, act : function(){

this._move();

} }

var myDog = new Animal("wangcai");

myDog.say();// I’m a(an) animal , my name is wangcai , I’m 20
myDog.setName("abc");//您设置的name值不合要求
alert(myDog.getName());// wangcai

myDog.setName("xiaoqiang");

alert(myDog.getName());// xiaoqiang myDog.setType("dog");// 赋值失败,Animal 类的 type 属性是只读的

代码清单 5-118监听属性的 valueChange

function Animal(name){ var name = name;

var type = "animal";

var _age = 20;

// 添加 master 属性,默认值为 adang var master = "adang";

this.getName = function(){ return name;

} this.setName = function(o){

if(o != "wangcai" && o != "xiaoqiang"){ alert("您设置的 name 值不合要求");

return;

} name = o;

// 触发 name 属性的 valueChange 事件 this._valueChangeHandler("name");

} // master 属性的获取方法

this.getMaster = function(){ return master;

} // master 属性的设置方法

this.setMaster = function(o){ master = o;

// 触发 master 属性的 valueChange 事件 this._valueChangeHandler("master");

} this.getType = function(){

return type;

} this.setType = function(o){

alert("赋值失败,Animal 类的 type 属性是只读的");

} this._getAge = function(){

_age = o;

} }

Animal.prototype = { _move : function(){

alert("I'm moving now");

}, say : function(){

alert("I'm a(an) " + this.getType() + " , my name is " + this.getName()

  • " , I'm " + this._getAge());

}, act : function(){

this._move();

}, // 公有行为,用于注册属性的 valueChange 事件

onChange : function(valueName,fun){ this["_" + valueName + "ChangeHadlers"] = this["_" + valueName +

"ChangeHadlers"] || [];

this["_" + valueName + "ChangeHadlers"].push(fun);

}, // 私有行为,属性 valueChange 的处理函数

_valueChangeHandler : function(valueName){ var o = this["_" + valueName + "ChangeHadlers"];

if(o){ for(var i=0,n=o.length;i<n;i++){

var methodName = "get" + valueName.charAt(0).toUpperCase()+valueName.slice(1);

o[i](this[methodName]());

} }

} }

var myDog = new Animal("wangcai");

// 给 myDog 注册 name 属性的 valueChange 事件 myDog.onChange("name",function(o){

// 回调函数接收新的 value 值作为参数,可以对其进行匹配 if(o == "xiaoqiang"){

alert(1);

} else { alert(2);

} });

// 给 myDog 换个新名字 xiaoqiang myDog.setName("xiaoqiang");// 1

//给 myDogg 再注册一个 name 属性的 valueChange 事件 myDog.onChange("name",function(o){

alert("my new name is " + o);

});

// 给 myDog 换个新名字 wangcai myDog.setName("wangcai");// 2, my new name is wangcai

// 给 myDog 注册 master 属性的 valueChange 事件 myDog.onChange("master",function(o){

alert("my new master is " + o);

})

// 给 MyDog 换个主人 myDog.setMaster("Yang Fuchuan");// my new master is Yang Fuchuan

alert(o + " is my new master");

})

myDog2.setMaster("Zhou Yubo");// Zhou Yubo is my new master

代码清单 5-119定义 Animal 类

// 定义 Animal 类 function Animal(name){

this.name = name;

this.type = "animal";

} Animal.prototype = {

say : function(){ alert("I'm a(an) " + this.type + " , my name is " + this.name);

} }

代码清单 5-120定义 Bird 类

// 定义 Animal 类 function Animal(name){

this.name = name;

this.type = "animal";

} Animal.prototype = {

say : function(){ alert("I'm a(an) " + this.type + " , my name is " + this.name);

} }

// 定义 Bird 类 function Bird(){

} Bird.prototype = {

}

代码清单 5-121继承构造函数中的属性和行为

// 定义 Animal 类 function Animal(name){

this.name = name;

this.type = "animal";

} Animal.prototype = {

say : function(){ alert("I'm a(an) " + this.type + " , my name is " + this.name);

} }

// 定义 Bird 类 function Bird(name){

this.name = name;

this.type = "animal";

} Bird.prototype = {

}

代码清单 5-122改进构造函数中的继承

// 定义 Animal 类 function Animal(name){

this.name = name;

this.type = "animal";

} Animal.prototype = {

say : function(){ alert("I'm a(an) " + this.type + " , my name is " + this.name);

} }

// 定义 Bird 类 function Bird(name){

Animal(name);

} Bird.prototype = {

}

// 实例化 Bird 对象 var myBird = new Bird("xiaocui");

alert(myBird.type);// undefined

代码清单 5-123实际效果

// 定义 Animal 类 function Animal(name){

this.name = name;

this.type = "animal";

} Animal.prototype = {

say : function(){ alert("I'm a(an) " + this.type + " , my name is " + this.name);

} }

// 定义 Bird 类 function Bird(name){

window.name = name;

window.type = "animal";

} Bird.prototype = {

}

// 实例化 Bird 对象 var myBird = new Bird("xiaocui");

alert(myBird.type);// undefined alert(type);// animal(window.type 可省略写成 type)

代码清单 5-124使用 call 方法指定 this 指向

// 定义 Animal 类 function Animal(name){

this.name = name;

this.type = "animal";

}

} }

// 定义 Bird 类 function Bird(name){

Animal.call(this,name);

} Bird.prototype = {

}

// 实例化 Bird 对象 var myBird = new Bird("xiaocui");

alert(myBird.type);// animal

代码清单 5-125原型的继承

// 定义 Animal 类 function Animal(name){

this.name = name;

this.type = "animal";

} Animal.prototype = {

say : function(){ alert("I'm a(an) " + this.type + " , my name is " + this.name);

} }

// 定义 Bird 类 function Bird(name){

Animal.call(this,name);

} Bird.prototype = Animal.prototype;

// 实例化 Bird 对象 var myBird = new Bird("xiaocui");

myBird.say();// I'm a(an) animal , my name is xiao cui

代码清单 5-126添加 fly 行为

// 定义 Animal 类 function Animal(name){

this.name = name;

this.type = "animal";

} Animal.prototype = {

say : function(){ alert("I'm a(an) " + this.type + " , my name is " + this.name);

} }

// 定义 Bird 类 function Bird(name){

Animal.call(this,name);

} Bird.prototype = Animal.prototype;

Bird.prototype.fly = function(){ alert("I'm flying");

}

myBird.say();// I'm a(an) animal , my name is xiao cui myBird.fly();// I’m flying

var myDog = new Animal("wangcai");

myDog.fly();// I’m flying

代码清单 5-127传值与传址

var a = 10;// 基本数据类型

var b = a;//将变量a保存的值复制一份,传给变量b,a和b各保存一份数据
var c = [1,2,3];//复杂数据类型
var d = c;//将变量c指向的数据的内存地址传给变量d,c和d指向同一份数据

b++;

d.push(4);

alert(a);// 10

alert(b);// 11变量b保存的数据更改不会影响到变量a
alert(c);// 1,2,3,4变量c和d指向同一份数据,数据更改会互相影响
alert(d);// 1,2,3,4
代码清单5-128对复杂数据类型进行传值

var a = [1,2,3] , b = {name:"adang",sex:"male",tel:"1234567"};

var c = [] , d = {};

for(var p in a){ c[p] = a[p];

} for(var p in b){

d[p] = b[p];

} c.push("4");

d.email = "xxx@gmail.com";

alert(a);// 1,2,3 alert(c);// 1,2,3,4

alert(b.email);// undefined alert(d.email);// xxx@gmail.com

代码清单 5-129数组传值的简单方法

var a = [1,2,3];

var b = a.slice() , c = a.concat();

b.pop();

c.push(4);

alert(a);// 1,2,3 alert(b);// 1,2

alert(c);// 1,2,3,4

代码清单 5-130改进原型继承

// 定义 Animal 类 function Animal(name){

this.name = name;

this.type = "animal";

} Animal.prototype = {

say : function(){ alert("I'm a(an) " + this.type + " , my name is " + this.name);

} }

// 定义 Bird 类 function Bird(name){

Bird.prototype.constructor = Bird;

Bird.prototype.fly = function(){ alert("I'm flying");

}

// 实例化 Bird 对象 var myBird = new Bird("xiaocui");

myBird.say();// I'm a(an) animal , my name is xiao cui myBird.fly();// I’m flying

var myDog = new Animal("wangcai");

myDog.fly();// 报错,myDog.fly is not a function

代码清单 5-131定义 extend 函数

function extend(subClass,superClass){ var F = function(){};

F.prototype = superClass.prototype;

subClass.prototype = new F();

subClass.prototype.constructor = subClass;

subClass.superclass = superClass.prototype;

if(superClass.prototype.constructor == Object.prototype.constructor){ superClass.prototype.constructor = superClass;

} }

function Animal(name){ this.name = name;

this.type = "animal";

} Animal.prototype = {

say : function(){ alert("I'm a(an) " + this.type + " , my name is " + this.name);

} }

function Bird(name){ this.constructor.superclass.constructor.apply(this,arguments);

this.type = "bird"

} extend(Bird,Animal);

Bird.prototype.fly = function(){ alert("I'm flying");

} var canary = new Bird("xiaocui");

canary.say();// I’m a(an) bird , my name is xiaocui canary.fly();// I’m flying

5.4.3用面向对象方式重写代码

代码清单 5-132用面向对象方式重写电话本程序

// 定义电话本管理类 function PhonebookManager(){

this._phonebook = null;

} PhonebookManager.prototype = {

// 查询电话 getTel : function(){

}, // 删除记录

removeItem : function(){

} }

代码清单 5-133定义行为的参数

// 定义电话本管理类 function PhonebookManager(o){

this._phonebook = o;

} PhonebookManager.prototype = {

// 查询电话 getTel : function(oName){

}, // 添加记录

addItem : function(oName,oTel){

}, // 删除记录

removeItem : function(oName){

} }

代码清单 5-134编写具体的行为代码

// 定义电话本管理类 function PhonebookManager(o){

this._phonebook = o;

} PhonebookManager.prototype = {

// 查询电话 getTel : function(oName){

var tel = "";

for(var i=0;i<this._phonebook.length;i++){ if(this._phonebook[i].name == oName){

tel = this._phonebook[i].tel;

break;

} }

return tel;

}, // 添加记录

addItem : function(oName,oTel){ this._phonebook.push({name:oName,tel:oTel});

}, // 删除记录

removeItem : function(oName){ var n;

for(var i=0;i<this._phonebook.length;i++){ if(this._phonebook[i].name == oName){

n = i;

break;

}

} }

}

代码清单 5-135使用面向对象的电话本程序

// 实例化两个电话本管理对象 var myPhonebookManager = new PhonebookManager([

{name:"adang",tel:"111111"}, {name:"zhangxia",tel:"222222"},

{name:"yangfuchuan",tel:"333333"}, {name:"qiaojiwu",tel:"444444"},

{name:"zhouyubo",tel:"555555"} ]),

myPhonebookManager2 = new PhonebookManager([ {name:"niaoren",tel:"111111"},

{name:"j2ee",tel:"222222"}, {name:"baobao",tel:"333333"}

]);

// 从电话本 1 中查询”niaoren”的电话 var str = myPhonebookManager.getTel("niaoren");

alert(str);// ""

// 在电话本 1 中添加”niaoren”的记录 myPhonebookManager.addItem("niaoren","666666");

str = myPhonebookManager.getTel("niaoren");

alert(str);// "666666"

// 在电话本 1 中删除”niaoren”的记录 myPhonebookManager.removeItem("niaoren");

str = myPhonebookManager.getTel("niaoren");

alert(str);// ""

// 在电话本 2 中查询”niaoren”的记录 str = myPhonebookManager2.getTel("niaoren");

alert(str);// "111111"

代码清单 5-136用面向对象方式重构 Tab

var GLOBAL = {};

GLOBAL.namespace = function(str){ var arr = str.split("."),o = GLOBAL;

for (i=(arr[0] == "GLOBAL") ? 1 : 0; i<arr.length; i++) { o[arr[i]]=o[arr[i]] || {};

o=o[arr[i]];

} }

GLOBAL.namespace("Dom");

GLOBAL.Dom.getElementsByClassName = function(str,root,tag){ if(root){

root = typeof root == "string" ? document.getElementById(root) : root;

} else { root = document.body;

} tag = tag || "*";

var els = root.getElementsByTagName(tag),arr = [];

for(var i=0,n=els.length;i<n;i++){

break;

} }

} return arr;

} GLOBAL.Dom.addClass = function(node,str){

if(!new RegExp("(^|\\s+)"+str).test(node.className)){ node.className = node.className + " " + str;

} }

GLOBAL.Dom.removeClass = function(node,str){ node.className = node.className.replace(new RegExp("(^|\\s+)"+str),"");

} GLOBAL.namespace("Event");

GLOBAL.Event.on = function(node,eventType,handler,scope){ node = typeof node == "string" ? document.getElementById(node) : node;

scope = scope || node;

if(document.all){

node.attachEvent("on"+eventType,function(){handler.apply(scope,arguments)})

;

} else {

node.addEventListener(eventType,function(){handler.apply(scope,arguments)}, false);

} }

function Tab(config){ this._root = config.root;

this._currentClass = config.currentClass;

var trigger = config.trigger || "click";

this._handler = config.handler;

var autoPlay = config.autoPlay;

var playTime = config.playTime || 3000;

this._tabMenus = GLOBAL.Dom.getElementsByClassName("J_tab-menu",this._root);

this._tabContents = GLOBAL.Dom.getElementsByClassName("J_tab-content",this._root);

this.currentIndex = 0;

var This = this;

if(autoPlay){ setInterval(function(){This._autoHandler()},playTime);

} for(var i=0;i<this._tabMenus.length;i++){

this._tabMenus[i]._index = i;

GLOBAL.Event.on(this._tabMenus[i],trigger,function(){ This.showItem(this._index);

this.currentIndex = this._index;

});

} }

Tab.prototype = { showItem : function(n){

for(var i=0;i<this._tabContents.length;i++){ this._tabContents[i].style.display = "none";

}

GLOBAL.Dom.getElementsByClassName(this._currentClass,this._root)[0];

if(currentMenu){ GLOBAL.Dom.removeClass(currentMenu,this._currentClass);

} GLOBAL.Dom.addClass(this._tabMenus[n],this._currentClass);

} if(this._handler){

this._handler(n);

} },

_autoHandler : function(){ this.currentIndex++;

if(this.currentIndex >= this._tabMenus.length){ this.currentIndex = 0;

} this.showItem(this.currentIndex);

} }

var tabs = GLOBAL.Dom.getElementsByClassName("J_tab");

new Tab({root:tabs[0],trigger:"mouseover"});

new Tab({root:tabs[1],currentClass:"tab-currentMenu",autoPlay:true,playTime:5000});

new Tab({root:tabs[2] , currentClass:"tab-currentMenu2" , trigger:"mouseover" , handler:function(index){alert("您激活的是第"+(index+1)+"个标签")}});

5.5其他问题

5.5.1prototype 和内置类

代码清单 5-137调用内置类

var a = new String("hello world");// 通过 new String()实例化 string 类型对象 var b = "hello world";// 直接通过""实例化 string 类型对象

alert(a.length);

alert(b.length);

var c = new Array(1,2,3);// 通过 new Array()实例化 array 类型对象 var d = [1,2,3];// 直接通过[]实例化 array 类型对象

c.push(4);

d.pop();

alert(c);

alert(d);

代码清单 5-138扩展内置类的行为

Array.prototype.each = function(fun){ for(var i = 0,n = this.length;i<n;i++){

fun(this[i],i);

} }

Array.prototype.clone = function(){ var o = [];

this.each(function(v,k){ o[k] = v;

});

return o;

} Array.prototype.map = function(fun){

});

return o;

} //因为 IE 中 delete 是保留字,所以方法名改用 Delete

Array.prototype.Delete = function(a){ var o = this.clone();

for(var i=o.length,n=0;i>n;i--){ if(o[i] == a){

o.splice(i,1);

} }

return o;

} var a = [1,2,3,2,4,5];

var str = "";

a.each(function(v,k){ str += k + " : " + v + "\n";

});

alert(str);// 0 : 1 1:2 2:3 3:2 4:4 5:5 var b = a.map(function(v,k){

return v * 10;

});

alert(a);// 1,2,3,2,4,5 alert(b);// 10,20,30,20,40,50

var c = b.Delete(20);

alert(c);// 10,30,40,50

代码清单 5-139重写内置类的方法

var a = [1,2,3];

alert(a);// 1,2,3 Array.prototype.toString = function(str){

return "I'm an array";

} alert(a);// I’m an array

代码清单 5-140自定义 toString 方法

function Dog(o){ this.name = o;

} var myDog = new Dog("wang cai");

alert(myDog);// [object Object] Dog.prototype.toString = function(){

return "my name is " + this.name;

} alert(myDog);// my name is wang cai

var me = { name : "adang",

email : "cly84920@gmail.com", toString : function(){

return "I'm adang,my email is cly84920@gmail.com";

} }

代码清单 5-141重写属性

Array.prototype.length = 1;

String.prototype.length = 1;

代码清单 5-142扩展 Object 类

Object.prototype.test = function(){ alert("hello world");

} var a = [1,2,3],b = "abc",c = {},d = true,e = function(){};

a.test();

b.test();

c.test();

d.test();

e.test();

function Dog(o){ this.name = o;

} Dog.prototype.toString = function(){

return "my name is " + this.name;

} var f = new Dog("wangcai");

f.test();

代码清单 5-143使用自定义类

function myArray(o){ this.getArray = function(){

return o;

};

} myArray.prototype = {

each : function(fun){ var o = this.getArray();

for(var i=0,n=o.length;i<n;i++){ fun(o[i],i);

} }

} var a = new myArray([1,2,3]),str = "";

a.each(function(v,k){ str += k + " : " + v + "\n";

});

alert(str);// 0 : 1 1 : 2 2 : 3

5.5.2标签的自定义属性

代码清单 5-144html 标签和 js 的映射

<a id="a" class="b" title="" href="http://www.adanghome.com"

onclick="alert(this.href);return false;">my blog</a> <script type="text/JavaScript">

var node = document.getElementById("a");

alert(typeof node);// object </script>

代码清单 5-145在 JavaScript 中获得 DOM 节点对象的属性

<a id="a" class="b" title="" href="http://www.adanghome.com"

onclick="alert(this.href);return false;">my blog</a> <script type="text/JavaScript">

var node = document.getElementById("a");

alert(node.getAttribute("id"));// a alert(node.id)// a

<a id="a" class="b" title="我的博客" href="http://www.adanghome.com"

onclick="alert(this.href);return false;">my blog</a> <script type="text/JavaScript">

var node = document.getElementById("a");

alert(node.getAttribute("id"));

/* IE 和 Firefox : a

*/

alert(node.getAttribute("class"));

/* IE: null

Firefox : b */

alert(node.getAttribute("className"));

/* IE: b

Firefox : null */

alert(node.getAttribute("title"));

/* IE 和 Firefox : 我的博客

*/

alert(node.getAttribute("href"));

/* IE 和 Firefox : http://www.adanghome.com

*/

alert(node.getAttribute("onclick"));

/* IE: function onclick(){

alert(this.href);return false;

} Firefox : alert(this.href);return false;

*/

alert(node.getAttribute("innerHTML"));

/* IE: my blog

Firefox : null */

alert(node.id);

/* IE 和 Firefox : a

*/

alert(node.className);

/* IE 和 Firefox : b

*/

alert(node.title);

alert(node.href);

/* IE 和 Firefox : http://www.adanghome.com

*/

alert(node.onclick);

/* IE: function onclick(){

alert(this.href);return false;

} Firefox : function onclick(event){

alert(this.href);

return false;

} */

alert(node.innerHTML));

/* IE 和 Firefox : my blog

*/

代码清单 5-147JavaScript 和 html 间的映射

<style type="text/CSS"> .red{color:red;}

</style> <span id="a">hello world</span>

<script type="text/JavaScript"> var node = document.getElementById("a");

node.className = "red";

</script>

代码清单 5-148自定义属性的获取

<a id="a" href="http://www.adanghome.com" blogName="阿当的博客" blogType="前端开发">my blog</a>

<script type="text/JavaScript"> var node = document.getElementById("a");

alert(node.blogName);

/* IE: 阿当的博客

Firefox : undefined */

alert(node.blogType);

/* IE: 前端开发

Firefox : undefined */

alert(node.getAttribute("blogName"));

/* IE 和 Firefox : 阿当的博客

*/

alert(node.getAttribute("blogType"));

/*

代码清单 5-149自定义属性的反序列化

<a id="a" href="http://www.adanghome.com" blogInfo="{name:'阿当的博客',type:'前端开发'}">my blog</a>

<script type="text/JavaScript"> var node = document.getElementById("a");

var info = node.getAttribute("blogInfo");

alert(typeof info);// string
alert(info.name);// undefined
alert(info.type);// undefined

info = eval("("+info+")");

alert(typeof info);// object
alert(info.name);//阿当的博客
alert(info.type);//前端开发

</script>

5.5.3标签的内联事件和 event 对象

代码清单 5-150简单的点击事件

<input type="button" id="btn" value="click me" />

<script type="text/JavaScript"> document.getElementById("btn").onclick = function(){

alert(arguments.length);

};

</script>

代码清单 5-151内联事件中的点击事件

<input type="button" id="btn" value="click me" onclick = "handler()" />

<script type="text/JavaScript"> function handler(){

alert(arguments.length);

};

</script>

代码清单 5-152替换可能一

btn.onclick = handler;

function handler(){ alert(arguments.length);

}

代码清单 5-153替换可能二

btn.onclick = function(){ handler();

} function handler(){

alert(arguments.length);

}

代码清单 5-154内联事件和参数

<input type="button" id="btn" value="click me" onclick = "alert(arguments[0].type)"

/>

<script type="text/JavaScript"> document.getElementById("btn").onclick = function(e){

e = window.event || e;//e 兼容 IE 和 Firefox,指向 event 对象 };

</script>

代码清单 5-156在内联事件中兼容 event 对象

<input type="button" id="btn" value="click me" onclick="alert(event.type);" />

代码清单 5-157内联事件的使用

//只弹出 1 <input type="button" id="btn" value="click me"

onclick="alert(1);//alert(2);alert(3);" />

//弹出 1 和 3 <input type="button" id="btn" value="click me"

onclick="alert(1);/*alert(2);*/alert(3);" />

//弹出“string”

<input type="button" id="btn" value="click me" onclick="var a='abc';alert(typeof a);"/>

代码清单 5-158在两处同时监听事件

<input type="button" id="btn" value="click me" onclick="alert(123);" />

<script type="text/JavaScript"> document.getElementById("btn").onclick = function(){

alert(456);

};

</script>

代码清单 5-159等同效果

<input type="button" id="btn" value="click me" />

<script type="text/JavaScript"> document.getElementById("btn").onclick = function(){

alert(123);

};

document.getElementById("btn").onclick = function(){ alert(456);

};

</script>

代码清单 5-160改进方案,同时监听两处事件

<input type="button" id="btn" value="click me" onclick="alert(123);" />

<script type="text/JavaScript"> function handler(){

alert(456);

} if(document.all){

btn.attachEvent("onclick",handler);

} else { btn.addEventListener("click",handler,false);

} </script>

5.5.4利用事件冒泡机制

代码清单 5-161打分程序

<!—- 编写 rate 相关的 html 结构 --> <h1>阿当饭店</h1>

<p>卫生:<p> <p class="J_rate">

<img src="star.gif" title="很烂" /> <img src="star.gif" title="一般" />

<img src="star.gif" title="还好" /> <img src="star.gif" title="较好" />

<img src="star.gif" title="很好" /> </p>

<p>价格:<p> <p class="J_rate">

<img src="star.gif" title="很烂" /> <img src="star.gif" title="一般" />

<img src="star.gif" title="还好" /> <img src="star.gif" title="较好" />

<img src="star.gif" title="很好" /></p> <p>味道:<p>

<p class="J_rate"> <img src="star.gif" title="很烂" />

<img src="star.gif" title="一般" /> <img src="star.gif" title="还好" />

<img src="star.gif" title="较好" /> <img src="star.gif" title="很好" />

</p> <script type="text/JavaScript">

// 封装 DOM、Event 接口 var GLOBAL = {};

GLOBAL.namespace = function(str){ var arr = str.split("."),o = GLOBAL;

for (i=(arr[0] == "GLOBAL") ? 1 : 0; i<arr.length; i++) { o[arr[i]]=o[arr[i]] || {};

o=o[arr[i]];

} }

GLOBAL.namespace("Dom");

GLOBAL.Dom.getElementsByClassName = function(str,root,tag){ if(root){

root = typeof root == "string" ?

document.getElementById(root) : root;

} else { root = document.body;

} tag = tag || "*";

var els = root.getElementsByTagName(tag),arr = [];

for(var i=0,n=els.length;i<n;i++){ for(var j=0,k=els[i].className.split("

"),l=k.length;j<l;j++){ if(k[j] == str){

arr.push(els[i]);

break;

} }

} return arr;

node = typeof node == "string" ? document.getElementById(node) : node;

scope = scope || node;

if(document.all){

node.attachEvent("on"+eventType,function(){handler.apply(scope,arguments)});

} else {

node.addEventListener(eventType,function(){handler.apply(scope,arguments)},false)

;

} }

// 定义 Rate 类 function Rate(rateRoot){

var root = typeof rateRoot == "string" ?

document.getElementById(rateRoot) : rateRoot;

var items = root.getElementsByTagName("img");

var imgs = ["star.gif","star2.gif"];

var rateFlag;

for(var i=0,n=items.length;i<n;i++){ items[i].index = i;

GLOBAL.Event.on(items[i],"mouseover",function(){ if(rateFlag) return;

for(var j=0;j<n;j++){ if(j<=this.index){

items[j].src = imgs[1];

} else { items[j].src = imgs[0];

} }

});

GLOBAL.Event.on(items[i],"mouseout",function(){ if(rateFlag) return;

for(var j=0;j<n;j++){ items[j].src = imgs[0];

} });

GLOBAL.Event.on(items[i],"click",function(){ if(rateFlag) return;

rateFlag = true;

alert("您打了"+(this.index+1)+"分");

});

} }

// 实例化 Rate 类 var rateNodes = GLOBAL.Dom.getElementsByClassName("J_rate");

for(var i=0,n=rateNodes.length;i<n;i++){ new Rate(rateNodes[i]);

} </script>

代码清单 5-162等同效果

<p class="J_rate"> <img src="star.gif" title="很烂" onmouseover="…" onmouseout="…" onclick="…" />

<img src="star.gif" title="一般" onmouseover="…" onmouseout="…" onclick="…" />

</p>

代码清单 5-163利用事件冒泡进行优化

// 定义 Rate 类 function Rate(rateRoot){

var root = typeof rateRoot == "string" ?

document.getElementById(rateRoot) : rateRoot;

var items = root.getElementsByTagName("img");

var imgs = ["star.gif","star2.gif"];

var rateFlag;

for(var i=0,n=items.length;i<n;i++){ items[i].index = i;

} GLOBAL.Event.on(root,"mouseover",function(e){

if(rateFlag) return;

var target = e.target || e.srcElement;

if(target.tagName.toLowerCase() != "img") return;

for(var i=0;i<n;i++){ if(i<=target.index){

items[i].src = imgs[1];

} else { items[i].src = imgs[0];

} }

});

GLOBAL.Event.on(root,"mouseout",function(e){ if(rateFlag) return;

var target = e.target || e.srcElement;

for(var i=0,n=items.length;i<n;i++){ items[i].src = imgs[0];

} });

GLOBAL.Event.on(root,"click",function(e){ if(rateFlag) return;

rateFlag = true;

var target = e.target || e.srcElement;

alert("您打了"+(target.index+1)+"分");

});

}

代码清单 5-164等同效果

<p class="J_rate" onmouseover="…" onmouseout="…" onclick="…"> <img src="star.gif" title="很烂" />

<img src="star.gif" title="一般" /> <img src="star.gif" title="还好" />

<img src="star.gif" title="较好" /> <img src="star.gif" title="很好" />

</p>

5.5.5改变 DOM 样式的三种方式

代码清单 5-165改变 DOM 节点样式的方法一

<span id="test">hello world</span> <script type="text/JavaScript">

var node = document.getElementById("test");

node.style.color = "red";

<span id="test" style="color:red">hello world</span>

代码清单 5-167用方法一改变多个样式

<span id="test">hello world</span> <script type="text/JavaScript">

var node = document.getElementById("test");

node.style.color = "red";

node.style.backgroundColor = "black";

node.style.fontSize = "40px";

node.style.fontWeight = "bold";

</script>

代码清单 5-168等同效果

<span id="test"

style="color:red;background-color:black;font-size:40px;font-weight:bold">hello world</span>

代码清单 5-169改变 DOM 节点样式的方法二

<style type="text/CSS"> .testStyle{color:red;background-color:black;font-size:40px;font-weight:bold;}

</style> <span id="test">hello world</span>

<script type="text/JavaScript"> var node = document.getElementById("test");

node.className = "testStyle";

</script>

代码清单 5-170等同效果

<style type="text/CSS"> .testStyle{color:red;background-color:black;font-size:40px;font-weight:bold;}

</style> <span id="test" class="testStyle">hello world</span>

代码清单 5-171需设置样式的 DOM 节点

<span id="test">hello world</span> <span>aaaaaa</span>

<span>bbbbbb</span> <span>cccccc</span>

代码清单 5-172等同效果一

<span id="test" style="font-size:40px;background:#000;color:red">hello world</span> <span style="font-size:40px;background:#000;color:#fff">aaaaaa</span>

<span style="font-size:40px;background:#000;color:#fff">bbbbbb</span> <span style="font-size:40px;background:#000;color:#fff">cccccc</span>

代码清单 5-173等同效果二

<style type="text/CSS"> .testStyle{font-size:40px;background:#000;color:#fff}

#test{color:red} </style>

<span id="test" class="testStyle">hello world</span> <span class="testStyle">aaaaaa</span>

<span class="testStyle">bbbbbb</span> <span class="testStyle">cccccc</span>

代码清单 5-174改变 DOM 节点样式的方法三

<span>cccccc</span> <script type="text/JavaScript">

function addStyleNode(str){ var styleNode = document.createElement("style");

styleNode.type = "text/CSS";

if(styleNode.styleSheet){ styleNode.styleSheet.cssText = str;

} else { styleNode.innerHTML = str;

} document.getElementsByTagName("head")[0].appendChild(styleNode);

} addStyleNode("span{font-size:40px;background:#000;color:#fff}

#test{color:red}");

</script>

代码清单 5-175等同效果

<style type="text/CSS"> span{font-size:40px;background:#000;color:#fff}

#test{color:red} </style>

<span id="test">hello world</span> <span>aaaaaa</span>

<span>bbbbbb</span> <span>cccccc</span>

附录前端规范

附录 A 写在规则前面的话

附录 B 命名规则

html:

<ul class=”textList”> <li class=”textList_firstItem”>1)XXXXXXXXXXXXXX</li>

<li>2)XXXXXXXXXXXXXX</li> <li>3)XXXXXXXXXXXXXX</li>

</u1>

CSS:

.textList{ } V.text_list{ } X .textList_firstItem{ } V.textListFirstItem{ } X

.textList_firstItem{ } V .textList .firstItem{ } X

附录 C 分工安排

附录 D 注释规则

/**

  • 文件用途说明
  • 作者姓名
  • 联系方式
  • 制作日期

**/

//代码说明 //姓名

var name = "abc";V

var name ="abc"; //姓名X

附录 E HTML 规范

<!--头部开始{--> <div class="head">

<div class="header clearfix"> <h1 class="fr">阿当制作</h1>

<h2 class="fb fl">阿当测试站点<span class="gray fn">的页面管理模式</span></h2> <input type="button" value="完成并退出" class="ml50 fl" />

</div> </div>

<!--}头部结束-->

附录 F CSS 规范

html:

<p>12345</p> <ul class="textList">

<li>1)XXXXXXXXXXX</li> <li>2)XXXXXXXXXXX</li>

</ul> <p>abcde</p>

<ul class="textList2"> <li>1)XXXXXXXXXXX</li>

<li>2)XXXXXXXXXXX</li> </ul>

CSS:

.textList,.textList2{margin-top:10px;XXXXXXXXXXXXXX} .textList2{margin-top:20px;}

X

=====================================================

html:

<p>12345</p> <ul class="textList marginTop10">

<li>1)XXXXXXXXXXX</li> <li>2)XXXXXXXXXXX</li>

</ul> <p>abcde</p>

<ul class="textList marginTop20"> <li>1)XXXXXXXXXXX</li>

<li>2)XXXXXXXXXXX</li> </ul>

CSS:

.textList{XXXXXXXXXXXXXX} .marginTop10{margin-top:10px;}

.marginTop20{margin-top:20px;} V

<p>XXXXXXXXXXXXX</p> <p class="marginTop10 marginBottom10">XXXXXXXXXXXX</p>

<p>XXXXXXXXXXXXX</p>

<p>XXXXXXXXXXXXX</p> <p class="marginTop10">XXXXXXXXXXXXX</p>

<p class="marginTop10">XXXXXXXXXXXXX</p> V

.menu{margin:0;float:left;font-weight:bold;}V .menu{

margin:0;

float:left;

font-weight:bold;

}X

附录 G JavaScript 规范

全站分卷索引 · 7 卷
  1. 1扉页
  2. 2版权页
  3. 3推荐序-张克军
  4. 4赞誉
  5. 5前言
  6. 6致谢
  7. 7目录