Chapter05
伪协议
可以用来链接JavaScript函数的伪协议: javascript:
<a href="javascript:function_name(parameter)">Example</a>
<a href="javascript:pop('http://www.baidu.com/')">Example</a>
但是这种做法非常不好。只有在支持伪协议和JavaScript的浏览器,才可使用。
平稳退化
平稳退化的失败例子:
<!--如果用户禁用JavaScript,则这个链接依然失效-->
<a href="#" onclick="popUp(this.href);return false;">Example</a>
平稳退化的成功例子:
<!--如果用户禁用JavaScript,则这个链接依然有效-->
<a href="http://www.example.com/" onclick="popUp(this.href);return false;">Example</a>
渐进增强
CSS
分离JavaScript
把JavaScript代码打包在prepareLinks函数里,并把这个函数添加到window对象的onload事件上去。
#JavaScript文件
window.onload = prepareLinks;
function prepareLinks(){
var links = document.getElementsByTagName("a");
for (var i=0; i<links.length;i++){
if (links[i].getAttribute("class") == "popup"){
links[i].onclick = function(){
popUp(this.getAttribute("href"));
return false;
}
}
}
}
function popUp(winURL){
window.open(winURL,"popup","width=320,height=480");
}
向后兼容
网页设计时应考虑到旧版浏览器的解析能力。
对象检测
向后兼容的一种最简单的解决方案。
if (method) {
//statements
}
window.onload = function(){
if (!document.getElementsByTagName) return false;
var links = document.getElementsByTagName("a");
for (var i=0; i<links.length;i++){
if (links[i].getAttribute("class") == "popup"){
links[i].onclick = function(){
popUp(this.getAttribute("href"));
return false;
}
}
}
}
但是这个方案的不足是:如果存在检测多个方法或者属性,就会出现非常多的嵌套或者检测语句,让代码显得臃肿难读。
浏览器嗅探技术
除了检测对象是否存在,还可以使用浏览器嗅探(browser snifung)。通过检索浏览器的品牌和版本来改善JS的向后兼容性。但是有风险,因为浏览器有时候信息并不标准,而且浏览器的版本迭代更新导致这个实现起来更难。
性能考虑
为了web的流畅性,应该考虑一些问题。
减少DOM访问和减少标记
尽量少访问DOM和尽量减少标记,在多个函数都会取得一组类似元素的情况下,可以考虑重构代码,把搜索结果保存在一个全局变量里,或者把一组元素直接以参数形式传递给函数。
合并和放置脚本
合并脚本可以减少HTTP请求的次数。
建议把所有的< script>标签都放到文档末尾,标签之前,可以让页面加载更快。
位于块中的脚本会导致浏览器无法并行加载其他文件(如图片或其他脚本),一般来说,根据HTTP规范,浏览器每次从同一域名中最多只能同时下载两个文件,在下载脚本期间,浏览器不会下载其他任何文件,即使是来自不同域名的文件也不会下载,所有其他资源都要等脚本加载完毕后才能下载。所以建议把所有的
压缩脚本
压缩脚本,指的是把脚本文件中不必要的字节(空格、注释等)统统删除。压缩后的代码虽然可读性差,但能大幅减少文件大小。多数情况下,应该有两个版本,一个是工作副本,可以修改代码并添加注释;另一个是压缩副本,用于放在服务器上。通常为了区分非压缩版本,最好在压缩副本的文件名中加上min字样。
压缩工具推荐,Douglas Crockford的JSMin、Google的Closure Compiler。
Chapter06
灵魂5连问:
它支持平稳退化吗?
“如果JavaScript功能被禁用,会怎样?”==>解决
<a href="images/fireworks.jpg" title="A fireworks display" onclick="showPic(this);return false;">Fireworks</a>
它的JavaScript与HTML标记是分离的吗?
- 添加挂钩
#gallery.html
<ul id="imagegallery">
<li>
<a href="images/fireworks.jpg" title="A fireworks display" onclick="showPic(this);return false;">Fireworks</a>
</li>
<li>
<a href="images/coffee.jpg" title="A cup of black coffee" onclick="showPic(this);return false;">Coffee</a>
</li>
<li>
<a href="images/rose.jpg" title="A red,red rose" onclick="showPic(this);return false;">Rose</a>
</li>
<li>
<a href="images/bigben.jpg" title="The famous clock" onclick="showPic(this);return false;">Big Ben</a>
</li>
</ul>
- 添加事件处理函数
#showPic.js
function prepareGallery(){
if (!document.getElementsByTagName) return false;
if (!document.getElementById) return false;
if (!document.getElementById("imagegallery")) return false;
var gallery = document.getElementById("imagegallery");
var links = document.getElementsByTagName("a");
for (var i=0; i<links.length; i++){
links[i].onclick = function(){
showPic(this);
return false;
}
}
}
- 共享onload事件
#showPic.js
# 方法一:建立匿名函数
window.onload = function(){
firstFunction();
secondFunction();
}
# 方法二:建立addLoadEvent函数
function addLoadEvent(func){
var oldonload = window.onload
if (typeof window.onload != 'function'){
window.onload = func;
}
else{
window.onload = function(){
oldonload();
func();
}
}
}
addLoadEvent(firstFunction);
addLoadEvent(secondFunction);
不要做太多的假设
需要在showPic()检查元素,并对于图片正常但text异常的状况对prepareGallery()作出修改。
#showPic.js
function showPic(whichpic){
if (!document.getElementById("placeholder")) return false;
var source = whichpic.getAttribute("href");
var placeholder = document.getElementById("placeholder");
placeholder.setAttribute("src",source);
if (document.getElementById("description")){
var text = whichpic.getAttribute("title");
var descrition = document.getElementById("description");
descrition.firstChild.nodeValue = text;
}
}
function prepareGallery(){
if (!document.getElementsByTagName) return false;
if (!document.getElementById) return false;
if (!document.getElementById("imagegallery")) return false;
var gallery = document.getElementById("imagegallery");
var links = document.getElementsByTagName("a");
for (var i=0; i<links.length; i++){
links[i].onclick = function(){
return !showPic(this);
}
}
}
优化
增加三元操作符来检查title属性(这是个费脑子的方法)
#showPic.js
var text = whichpic.getAttribute("title")? whichpic.getAttribute("title"):"";
键盘访问
最好不要使用onkeypress事件处理函数,用户每按下一个按键都会触发它。建议使用onclick事件处理函数,它也可以使用键盘Enter点击链接。
把JavaScript与CSS结合起来
利用挂钩可以用在CSS样式表里。
#gallery.html
在这里插入代码片
#layout.css
#imagegallery{
list-style: none;
}
#imagegallery li{
display: inline;
}
DOM Core和HTML-DOM
以下等价
document.getElementsByTagName("form");
document.forms;
placeholder.setAttribute("src",source);
placeholder.src = source;
综合代码
#showPic.js
function showPic(whichpic){
if (!document.getElementById("placeholder")) return false;
var source = whichpic.getAttribute("href");
var placeholder = document.getElementById("placeholder");
placeholder.setAttribute("src",source);
if (document.getElementById("description")){
var text = whichpic.getAttribute("title")? whichpic.getAttribute("title"):"";
var descrition = document.getElementById("description");
descrition.firstChild.nodeValue = text;
}
}
function prepareGallery(){
if (!document.getElementsByTagName) return false;
if (!document.getElementById) return false;
if (!document.getElementById("imagegallery")) return false;
var gallery = document.getElementById("imagegallery");
var links = document.getElementsByTagName("a");
for (var i=0; i<links.length; i++){
links[i].onclick = function(){
return !showPic(this);
}
}
}
function addLoadEvent(func){
var oldonload = window.onload
if (typeof window.onload != 'function'){
window.onload = func;
}
else{
window.onload = function(){
oldonload();
func();
}
}
}
#layout.css
body{
font-family: "Helvetica","Arial",serif;
color: #333;
background-color: #ccc;
margin: 1em 10%;
}
h1{
color: #333;
background-color: transparent;
}
a{
color: #c60;
background-color: transparent;
font-weight: bold;
text-decoration: none;
}
ul{
padding: 0;
}
li{
float:left;
padding: 1em;
}
img{
display: block;
clear: both;
}
#imagegallery{
list-style: none;
}
#imagegallery li{
display: inline;
}
#gallery.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<title>
Image Gallery
</title>
<link rel="stylesheet" href="styles/layout.css" type="text/css" media="screen">
</head>
<body>
<h1>Snapshots</h1>
<ul id="imagegallery">
<li>
<a href="images/fireworks.jpg" title="A fireworks display">Fireworks</a>
</li>
<li>
<a href="images/coffee.jpg" title="A cup of black coffee">Coffee</a>
</li>
<li>
<a href="images/rose.jpg" title="A red,red rose">Rose</a>
</li>
<li>
<a href="images/bigben.jpg" title="The famous clock">Big Ben</a>
</li>
</ul>
<img id="placeholder" src="images/placeholder.gif" alt="my image gallery">
<p id="description">Choose an image.</p>
<script src="scripts/showPic.js"></script>
</body>
</html>