如何将渐进增强应用到javascript脚本
原文:Progressive Enhancement with JavaScript
作者: Aaron Gustafson
如果你阅读了本系列的第一篇和第二篇文章,现在应当开始进入渐进增强的思维模式了。本文讨论如何将渐进增强的哲学应用到客户端脚本。你将很快看到,这涉及两个方面:约束与规划。
聪明地支配能力
也许你已经听说过“权力腐败”。这个词能引发很多联想,不过根据我们的用意,还是继续将其看成两个简单的词吧。JavaScript是一个能力强大到让人难以置信的工具,很长一段时间它的威力让web一团糟。它给web冲浪者扔下路障、错误信息还有太多的弹出窗口。对JavaScript的极大误解,可能导致了它的滥用,并使其在实践中更像一门黑色艺术。
JavaScript不仅造成的伤害多过好处,它还变得难以控制。实质上,它就像一辆破自行车,除了铃儿不响,其它哪儿都响。因为晦涩并经常私下开发的代码分支迅速繁殖,维护也是一场噩梦。
当年,JavaScript只能是丑陋的:浏览器还需对适当标准提供支持,而开发者们正忙于在HTML中书写像意大利面条一般杂乱的代码。为了完成跨浏览器兼容的任何事情,甚至简单得像图像翻转,JavaScript也必须解决很多令人头疼的问题。
谢天谢地,我们现在的处境好多了,终于能使得JavaScript代码干净许多。然而,我们必须尊重JavaScript的能力并且表现得负责。我们需要关注JavaScript如何使用,或许更需要关注JavaScript能做什么。我们需要学会约束。渐进增强能够帮助我们做到这一点,因为它让我们关注内容并且从内容开始构建。
建立基线
使用渐进增强,我们在可用代码的基础上构建站点。JavaScript的关键理念需要牢记于心:即便没有客户端脚本,任何用户需要用来理解页面意图的内容也应当存在于该页面中。这是第一课。
例如:上面讨论的内容可能是一个售出产品的对照表格。如果站点的需求指明在点击列头时,需要对数据排序,你可能会考虑通过Ajax来将数据加载到页面中,这样发送简短的请求就可以在服务器端进行排序。看起来很美妙,不是吗?
错了。
当禁用JavaScript的潜在用户访问该页面时,会发生什么?如果内容通过JavaScript加载到页面,这些用户根本访问不到内容,即便在没有排序的状态。如果他们连产品都看不见,你认为他们达成交易的可能性还有多大呢?
上面的场景还没有考虑到搜索的影响。搜索引擎爬虫不会执行JavaScript,因此如果使用JavaScript来将内容加载到页面,搜索引擎将永远不会读取或索引你的内容。如果产品信息不能在Google, Microsoft或Yahoo中索引和搜索到,你将丧失多少潜在客户?
如果带着渐进增强的想法,为了完成上面同样的需求,可以将基本的表格包含在HTML标记中。大部分情况下依旧需要后台程序来生成,但是需要直接嵌入在页面中而不是通过Ajax来加载。你仍然需要编写脚本,在DOM中找到表格,使其具有交互性,生成排序链接,并在它们的onclick
事件中绑定Ajax调用,最后打造出一个可排序的表格。
用这种方式完成挑战,不但满足了需求,还为搜索引擎爬虫和没有JavaScript的用户提供了一个“低保真”的体验。
再考虑远些,甚至还可以给表格头部手动添加一些排序链接,通过传递排序表格的相应参数,让它们能刷新页面。这使得没有JS的用户也能重新对数据排序,虽然响应速度稍微慢些,但仍然是功能齐全的“高保真”体验。
在脚本中加入些简单的小调整,还可以通过hijack技术让上面的排序链接依旧像以前一样执行Ajax请求,将最好的体验带来大部分有能力的用户。最后,你拥有了一个渐进增强实战的完美例子。
到这里,已经拥有了对JavaScript渐进增强的基本理解,我们能够讨论一些可以立刻使用的技巧了。
让脚本可控
有效集成渐进增强的一个关键是为脚本的管理建立规划。为了做到这一点,首先要熟悉“无侵入式JavaScript”的概念。无侵入式JavaScript是渐进增强在客户端脚本世界的基础。
“做到无侵入”最明显的办法是去掉所有行内的事件处理器,因为它们可以很简单地通过DOM来注册:
<a href="http://msdn.com"onclick="return newWin(this.href);">
接下来,将所有脚本移动到外链的文件中,而不是嵌入在script
元素中:
<script type="text/javascript"> // my script </script><script type="text/javascript" src="myscript.js"></script>
这可以让维护变得更轻松同时让你拥有一些代码库。(坦率地说,这两个变化可能需要不少工作量,因为这么多所见即所得编辑器和web应用程序开发框架生成可怕的侵入式JavaScript代码。值得庆幸的是,很多系统已经有补丁和插件用来克服它们的坏习惯。)
要使得脚本无侵入,接下来的步骤是决定何时以及如何包含它们。在最简单的层次上,这意味着检查,调用方法前先测试是否支持此方法,以确保脚本能在用户浏览器上运行:
if( document.getElementById ){ scriptUsingGetElementById(); }
你可能还想测试所有需要的对象,甚至还想测试用作脚本钩子的标识元素是否存在。对使用的每个脚本都按这个流程走,可以创建一个点菜式的交互体验,只有那些用户浏览器可以处理以及当前页面需要的脚本会被执行。
关于无侵入式JavaScript的更多介绍,请再次访问Jeremy Keith’s关于此议题的文章。
保持样式分离
JavaScript不存在于真空中。就如同应当让脚本和标记保持一定的分离(如上所述),也应当让脚本和样式保持一定的分离。
总的来说,当你在DOM中创建或操作元素时,必须停止添加行内样式,而应该应用类名,该类存在于全局样式表或某个脚本特定的样式表中:
var el = document.getElementById( 'message' );el.style.color = '#f00'; el.style.backgroundColor = '#ffcfcf';el.className = 'highlighted';
如果脚本需要很多样式来激活交互,采用脚本特定的样式表是个很不错的选择。在使用样式表的脚本中设置这些样式表,可以使得它们的维护能独立于站点上的其它样式表。这还能使得仅在脚本执行时才链接这些样式表,这样,对于没有使用该脚本或不支持该脚本的浏览器中的页面,能减少下载次数。
如果你决定将样式嵌入在某个主要样式表中,一定要采用上面的方法来给元素添加样式,以使得这些样式仅在脚本成功运行时才会被应用。
关于样式和脚本分离的更多信息,请阅读Scroll杂志首刊的这篇文章(目前只有印刷版本)。
取得进步
我们回顾了在JavaScript中实现渐进增强所需要的心态,以及做到渐进增强的若干技术。我们还接触到了无侵入式脚本的概念,并学会了少许技巧来管理CSS和JavaScript的内部关系。
本文完成了我们介绍性的系列文章,该系列关注渐进增强以及在CSS和JavaScript中实现渐进增强的方法。希望能引发你的思考并激励你开始在工作流程中使用渐进增强。