最佳实践

平稳退化

网站的访问者完全有可能使用的是不支持Javascript的浏览器,还有一种可能是虽然浏览器支持Javascript,但用户已经禁用它了。如果没有考虑到这种情况,人们在访问你们的网站时就有可能遇到各种各样的麻烦,并因此不再来访问你们的网站。

如果正确使用了Javascript脚本,就可以让访问者在他们的浏览器不支持Javascript的情况下仍能顺利地浏览你的网站。这就是所谓的平稳退化,就是说,虽然某些功能无法使用,但最基本的操作仍能顺利完成。

下面来看一个在新窗口中打开一个链接的例子:

function popUp(winURL){

window.open(winURL,"popup","width=320, height=480");

}

<a href="#" onclick="popUp('http://www.example.com/'); return false;">Example</a>

在这个实例中,实际工作都由onclick属性负责完成,不能平稳退化。

在链接里把href属性设置为真实存在的URL地址,让它成为一个有效的链接:

<a href="http://www.example.com/" onclick="popUp('http://www.example.com/'); return false;">Example</a>

或者

<a href="http://www.example.com/" onclick="popUp(this.getAttribute('href')); return false;">Example</a>

或者

<a href="http://www.example.com/" onclick="popUp(this.href); return false;">Example</a>

这三种方法都是可以的。

在把href属性设置为真实存在的URL地址之后,即使Javascript已被禁用,这个链接也是可用的。虽然这个链接在功能上打了点折扣(因为它没有打开一个新窗口),但是它并没有彻底失效。这是一个经典的“平稳退化”的例子。

这个技巧最明显的不足是:每当需要打开新的窗口时,就不得不把Javascript代码嵌入标记文档中。如果能把包括事件处理函数在内的所有Javascript代码全部放在外部文件里,这个技巧将更加完善。

向CSS学习

我们经常会遇到一些几乎每个元素都带有style属性的Web文档,而这是CSS技术最缺乏效率的用法之一。真正能从CSS技术获益的方法,是把样式全部转移到外部文件中去。

文档结构和文档样式的分离可以确保网页都能平稳退化。

所谓“渐进增强”就是用一些额外的信息层去包裹原始数据。按照“渐进增强”原则创建出来的网页几乎都符合“平稳退化”原则。

类似于CSS,Javascript和DOM提供的所有功能也应该构成一个额外的指令层。类似于使用style属性,在HTML文档里使用诸如onclick之类的属性也是一种既没有效率又容易引发问题的做法。如果我们用一个“挂钩”,就像CSS机制中的class或者id属性那样,把Javascript代码调用行为与HTML文档的结构和内容分离开,网页就会健壮得多。那么怎么把上面示例中的Javascript代码分离出来呢?

<a href="http://www.example.com/" class="popup">Example</a>

在外部的Javascript文件里把一个事件添加到HTML文档中的某个元素上:

element.event = action...

关键是怎么把应该获得这个事件的元素确定下来。具体步骤如下:

(1)把文档里的所有链接全放入一个数组里;

(2)遍历数组;

(3)如果某个链接的class等于popup,就表示这个链接在被点击时应该调用popUp()函数。

下面是实现上述步骤的Javascript代码:

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;

}

}

}

还有个问题需要解决:如果把这段代码存入外部Javascript文件,它将无法正常运行。因为这段代码的第一行是:

var links = document.getElementsByTagName("a");

这条语句将在Javascript文件被加载时立刻执行。如果Javascript文件是从HTML文档的<head>部分用<script>标签调用的,它将在HTML文档之前加载到浏览器里。同样如果<script>标签位于文档底部</body>之前,就不能保证哪个文件最先结束加载(浏览器可能一次加载多个)。因为脚本加载时文档可能不完整,所以模型也不完整。没有完整的DOM,getElementsByTagName等方法就不能正常工作。

必须让这些代码在HTML文档全部加载到浏览器之后马上开始执行。还好,HTML文档全部加载完毕时将触发一个事件,这个事件有它自己的事件处理函数。我将把我的Javascript代码打包在prepareLinks函数里,并将这个函数添加到window对象的onload事件上去。这样一来,DOM就可以正常工作了:

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;

}

}

}

}

别忘记把popUp函数也保存到那个外部Javascript文件里去。

向后兼容

你的网站的访问者很可能未启用Javascript功能,而且不同的浏览器对Javascript的支持程度也不一样。绝大多数浏览器都能或多或少地支持Javascript,而绝大多数现代的浏览器对DOM的支持都非常不错。但比较古老的浏览器却很可能无法理解DOM提供的方法和属性。因此,即使某位用户在访问你的网站时使用的是支持Javascript的浏览器,某些脚本也不一定能正常工作。

针对这一问题的最简单的解决方案是,检测浏览器对Javascript的支持程度。

if(!getElementsByTagName || !getElementById) return false;

按照这一思路,在用来把onclick事件添加到链接上去的网页加载脚本里插入一条if语句。

window.onload = prepareLinks;

function prepareLinks(){

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;

}

}

}

}

虽然只是一条if语句,但它可以确保那些“古老”的浏览器不会因为我的脚本代码而出问题。这么做是为了让脚本有良好的向后兼容性。

浏览器嗅探技术

在Javascript脚本代码里,在使用某个特定的方法或属性之前,先测试它是否真实存在是确保向后兼容性最安全和最可信的方法,但它并不是唯一的方法。在浏览器市场群雄逐鹿的那个年代,一种称为浏览器嗅探的技术曾经非常流行。

“浏览器嗅探”指通过提取浏览器供应商提供的信息来解决向后兼容问题。从理论上讲,可以通过Javascript代码检索关于浏览器品牌和版本的信息,这些信息可以用来改善Javascript脚本代码的向后兼容性,但这是一种风险非常大的技术。

首先,浏览器有时会“撒谎”。因为历史原因,有些浏览器会把自己报告成为另外一种浏览器,还有一些浏览器允许用户任意修改这些信息。

其次,为了适用于多种不同的浏览器,浏览器嗅探脚本会变得越来越复杂。如果想让浏览器嗅探脚本能够跨平台工作,就必须测试所有可能出现的供应商和版本号组合。这是一个无穷尽的任务,测试的组合情况越多,代码就越复杂和冗长。

最后,许多浏览器嗅探脚本在进行这类测试时要求浏览器的版本号必须得到精确的匹配。因此,每当市场上出现新版本时,就不得不修改这些脚本。

令人感到欣慰的是,充满着风险的浏览器嗅探技术正在被更简单也更健壮的对象检测技术所取代。

性能考虑

尽量少访问DOM和尽量减少标记:

不管什么时候,只要是查询DOM中的某些元素,浏览器就会搜索整个DOM树,从中查找可能匹配的元素;

另外,过多不必要的元素只会增加DOM树的规模,进而增加遍历DOM树以查找特定元素的时间。

合并和放置脚本:

把脚本都合并到一个脚本文件中,可以减少加载页面时发送的请求数量。而减少请求数量通常都是在性能优化时首先要考虑的。

把<script>标签放到别的地方并不是问题,但把所有<script>标签放到文档的末尾,</body>标记之前,就可以让页面变得更快。即使这样,在加载脚本时,window对象的load事件依然可以执行对文档进行的各种操作。

压缩脚本:

所谓压缩脚本,指的是把脚本文件中不必要的字节,如空格和注释,统统删除,从而达到“压缩”文件的目的。好在,有很多工具都可以替你来做这件事。有的精简程序甚至会重写你的部分代码,使用更短的变量名,从而减少整体文件大小。精简后的代码虽然不易看懂,却能大幅减少文件大小。多数情况下,你应该有两个版本,一个是工作副本,可以修改代码并添加注释;另一个是精简副本,用于放在站点上。通常,为了与非精简版本区分开,最好在精简副本的文件名中加上min字样。

下面是推荐给读者的几个有代表性的代码压缩工具:

Douglas Crockford 的JSMin

雅虎的YUI Compressor

谷歌的Closure Compiler

<!--

作者:纤锐
出处:http://www.cnblogs.com/beginner2014/p/4163056.html
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。谢谢合作。

-->

JavaScript DOM 编程艺术(第2版)读书笔记(5)的更多相关文章

  1. Javascript DOM 编程艺术(第二版)读书笔记——基本语法

    Javascript DOM 编程艺术(第二版),英Jeremy Keith.加Jeffrey Sambells著,杨涛.王建桥等译,人民邮电出版社. 学到这的时候,我发现一个问题:学习过程中,相当一 ...

  2. 读书笔记:JavaScript DOM 编程艺术(第二版)

    读完还是能学到很多的基础知识,这里记录下,方便回顾与及时查阅. 内容也有自己的一些补充. JavaScript DOM 编程艺术(第二版) 1.JavaScript简史 JavaScript由Nets ...

  3. 《JavaScript DOM编程艺术(第二版)》读书总结

    这本书是一本很基础的书,但对于刚入前端不久的我来说是一本不错的书,收获还是很大的,对一些基础的东西理解得更加透彻了. 1.DOM即document object model的缩写,文档对象模型,Jav ...

  4. 【读书笔记】读《JavaScript DOM 编程艺术-第2版》

    1.DHTML DHTML曾被认为是HTML/XHTML.CSS和JavaScript相结合的产物,就像今天的HTML5那样,但把这些东西真正凝聚在一起的是DOM.如果真的需要来描述这一过程的话,“D ...

  5. Javascript DOM 编程艺术(第二版)读书笔记——DOM基础

    1.DOM是什么 D=document(文档) O=object(对象) M=Model(模型) DOM又称节点树 一些术语: parent(父)   child(子)   sibling(兄弟)   ...

  6. JavaScript -- JavaScript DOM 编程艺术(第2版)

    /* 渐进增强 平稳退化 网页 结构层(structural layer): HTML 表示层(presentation layer): CSS <link rel="styleshe ...

  7. 《JavaScript DOM 编程艺术 第 2 版》

    第 5 章 最佳实践 平稳退化:现在基本所有带交互的网站都使用 Ajax,SAP 也火起来了,平稳退化真是很难实现了(看到第七章发现我之前的观点是错了) 分离 JS 向下兼容 性能考虑 第 6 章 案 ...

  8. JavaScript DOM编程艺术读后感(1)—— 平稳退化

    最近,在读<JavaScript DOM编程艺术(第二版)>这本书,想着将自己的读后感记录下来,作为记忆吧. 其实我并不是最近才刚开始读这本书的,我读了有一段时间了.我是一名web前端开发 ...

  9. JavaScript DOM编程艺术(第2版)的简单总结

    介绍 JavaScript DOM编程艺术(第2版)主要讲述了 JavaScript.DOM 和 HTML5 的基础知识,着重讲述了 DOM 编程,并通过几个实例演示了具有专业水准的网页开发. 下面介 ...

  10. 《JavaScript Dom 编程艺术》读书笔记-第4章

    我的前端入门第一本书是<JavaScript Dom 编程艺术>,网上查找资料发现前端的入门推荐书籍最受好评的就是这本和<JavaScript 高级程序设计>了.之所以先选这本 ...

随机推荐

  1. UI-UIImageView的图片填充方式(contentMode)_图片作为控件背景图的拉伸方式(stretch)介绍

    常用图片填充方式 这里只介绍三个最常用的图片填充方式 UIViewContentModeScaleToFill模式会导致图片变形.例如: UIViewContentModeScaleAspectFit ...

  2. linux:磁碟与档案系统管理

    档案系统特性:为什么磁碟分割完需要格式化(format)才能使用吗? 答:因为每种作业系统所设定的档案属性和权限并不相同,为了存放这些档案所需的资料(所以需要格式化成作业系统能够利用的档案系统格式fi ...

  3. 内存溢出之Tomcat内存配置

    设置Tomcat启动的初始内存其初始空间(即-Xms)是物理内存的1/64,最大空间(-Xmx)是物理内存的1/4. 可以利用JVM提供的-Xmn -Xms -Xmx等选项可进行设置 三.实例,以下给 ...

  4. yii中sphinx索引配置解析

    #MySQL数据源配置,详情请查看:http://www.coreseek.cn/products-install/mysql/#请先将var/test/documents.sql导入数据库,并配置好 ...

  5. android linux

    app 权限 - shell 权限2000 system root .adb 指令 a.查看链接终端设备 adb devices b.进入设备终端 adb shell ;多台设备 adb -s 设备号 ...

  6. paper 8:支持向量机系列五:Numerical Optimization —— 简要介绍求解求解 SVM 的数值优化算法。

    作为支持向量机系列的基本篇的最后一篇文章,我在这里打算简单地介绍一下用于优化 dual 问题的 Sequential Minimal Optimization (SMO) 方法.确确实实只是简单介绍一 ...

  7. MVC4中下拉菜单和单选框的简单设计方法

    举例一: @Html.LabelFor(model => model.Gender) @Html.DropDownListFor(model => model.Gender, new[] ...

  8. Oracle数据类型总结

    一 字符串类型 1.1:CHAR类型 CHAR(size [BYTE | CHAR]) CHAR类型,定长字符串,会用空格填充来达到其最大长度.非NULL的CHAR(12)总是包含12字节信息.CHA ...

  9. [Ubuntu] Ubuntu14.04 64bit 编译安装nginx1.7+php5.4+mysql5.6

    我的操作系统是Ubuntu14.04,其它linux系统的操作流程类似. 主要安装的软件是nginx1.7+php5.4+mysql5.6 1. 创建必要目录 sudo mkdir ~/setup s ...

  10. 《zw版·Halcon-delphi系列原创教程》 水果自动分类脚本(机器学习、人工智能)

    <zw版·Halcon-delphi系列原创教程> 水果自动分类脚本(机器学习.人工智能) 前面介绍了超市,流水线,酸奶的自动分类算法,下面再介绍一个水果的自动分类算法. Halcon强大 ...