您的位置:首页 > Web前端 > HTML5

几行代码完全解决HTML5在低版本浏览器中兼容性问题

2016-06-11 00:00 537 查看
 HTML5 有许多激动人心的特性,有了新的标签、新的CSS 能力和新的JavaScript API,Web 的能力范围有了大的飞跃。除了浏览器厂商的士气高涨之外,令人激动的新功能列表几乎每天都在增加。从“nightly builds”(每夜都构建一版)到开发渠道发行版和正常的平台预览版,浏览器在飞速变化,世界各地Web 开发人员们正在加入这个狂欢。
但是,尽管开发和浏览器社区正在把HTML5 的喧嚣推到一个极度兴奋的高潮,网上的大多数人却不像我们一样使用最新的浏览器和最新版本。如果你是一个大型开发机构的Web 开发人员或者是拥有庞大用户群的大企业,那你对此可能很清楚。即使你为通过Web 提供服务的小型机构或新创立的企业工作,你可能也要花上大量时间来确保自己的网站能够支持尽可能多的浏览器和浏览器版本。  
基于这一现实,很容易看出,HTML5 还谈不到它是否已为当今的使用做好准备,而是你是否为它做好了准备。例如,假设你用一些新的语法标签(例如和)新建了一个页面,添加了一些新的CSS 功能,例如圆角(border-radius)和阴影(box-shadow),甚至添加了一个元素在页面上绘制出一个HTML5 标识。  
在较新的浏览器上,例如Internet Explorer 9、Firefox 4 及以上版本、或者Google Chrome上,这个页面的显示如图1 所示。但如果尝试在Internet Explorer 8 或更早的浏览器上加载页面,很有可能看到的是图2 所示的效果:一个残缺不全的页面。



1 小时前 上传

下载附件 (77.97 KB)

  如果你在研究HTML5 的所有强大功能却得到上述体验之后告诉自己说:最好还是等等,那么我不会对你有任何责怪。如果我问你准备好了吗?你很容易得出这样的结论:HTML5 还没有为你或你的用户做好准备。  
在你决定等到2022 年再考虑HTML5 的之前,我建议你继续阅读本文的后面部分,我将向你提供一些实用的策略,让你现在就能采用HTML5 技术,同时避免出现图2 所示的糟糕的降级情况。我将从下面三个主题进行详细地介绍:
  •功能检测与用户代理(UA)嗅探比较
  •用 JavaScript 实现填补(Polyfill)
  •优雅降级
  这些应该可以教会你很多构建支持各种浏览器的网站所需要了解的知识。在本文结束时,你会拥有一个可靠的策略,可以充满自信、毫不犹豫地采用HTML5 技术。你还会拥有一些工具在手,可以逐步地为新浏览器增强网站,同时更好地适应旧的浏览器。因为HTML5 的采用策略就是一个浏览器也不放弃。
  一、功能检测的重要性
  为了提供跨浏览器的稳定且一致的体验,开发人员经常需要获得一些关于用户浏览器的信息。以前的普遍做法是像下面这样用JavaScript 检测这些信息:  

varuserAgent = navigator.userAgent;

if (userAgent.indexOf('MSIE') >= 0) {

console.log("Hello, IE user");

} else if (userAgent.indexOf('Firefox') >= 0) {

console.log("Hello, Firefox user");

} else if (userAgent.indexOf('Chrome') >= 0) {

console.log("Hello, Chrome user");

}

复制代码

  这个技术称为用户代理(UA)嗅探,广泛地用于判断正在请求页面的是哪个浏览器。这里的思路是:知道了用户的浏览器(例如IE7),就能在运行的时候决定启用或禁用网站的哪项功能。UA 嗅探就相当于对浏览器说:“你是谁?”(对UA 嗅探以及其他检测技术的深入分析,请参阅http://t.cn/zOi5m72)
  这种做法的问题在于,浏览器会撒谎。UA 字符串是一个用户可以配置的信息,并不会提供100%正确的浏览器信息。而且,随着这一技术的广泛采用,许多浏览器厂商在自己的UA 字符串中增加了额外内容,用来欺骗脚本,让脚本对于实际使用的浏览器做出错误判断,从而避免检测。现在有些浏览器甚至提供小工具,允许用户只要轻轻点击几下鼠标,就能修改UA 字符串。
  UA 嗅探的目的从来就不是确定用户的浏览器和版本。而且它肯定也不是为了在你不喜欢用户使用的浏览器时,让你可以告诉用户说“请下载另一个浏览器”——即使有些人就是这样使用UA 嗅探技术的。用户有权选择自己使用什么浏览器,开发人员的职责则是提供最可靠且一致的体验,不要把浏览器的偏好强加给用户。UA 嗅探的目标是让你能够准确地了解在用户当前的浏览器中,有哪些能力或功能可以利用。对浏览器本身的了解,只是获得这些信息的一个途径。目前有一些UA 嗅探的替代技术,其中一项正在日益流行的技术称为对象检测或功能检测。这两个术语多数时候可以互换使用,但本文统一使用“功能检测”(feature detection)。功能检测的目标是判断某项功能或能力在用户当前的浏览器中是否受支持。如果UA 嗅探是问浏览器“你是谁”,“功能检测”就是问浏览器“你能干什么”,这个问题更直接,对于根据条件向用户提供功能来说,这种方法也更可靠。如果功能检测脚本实现正确,用户或浏览器将很难造假或错报功能支持。

  二、手动功能检测
  那么,与UA 嗅探的示例相比,功能检测到底是什么样呢?为了回答这个问题,我们先来看看如果在Internet Explorer 8 中查看前面的HTML5 页面(如图1 所示),如何解决出现的问题。这个页面的标签内容如代码段1 所示。

<!DOCTYPE html>

<htmllang="en">

<head>

<meta charset="utf-8" />

<title>My Awesome Site</title>

<style>

body { font-size: 16px; font-family: arial,helvetica,clean,sans-serif; }

header h1 { font-size: 36px; margin-bottom: 25px; }

article

{

background: lightblue;

margin-bottom: 10px;

padding: 5px;

border-radius: 10px;

box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.5);

}

article h1 { font-size: 12px; }

</style>

</head>

37

<body>

<header><h1>My Awesome Site</h1></header>

<article>

<header><h1>An Article</h1></header>

<p>Isn't this awesome?</p>

</article>

<canvas width="250" height="500"></canvas>

</body>

<script src="../js/html5CanvasLogo.js" type="text/javascript"></script>

</html>

复制代码
  代码段1 带有HTML5 新语义标签的页面
  如图1图2 所示,Internet Explorer 9 和 Internet Explorer 8 的显示效果有很大的差别。对于初学者来说,我的页面完全没有样式,因为这个页面的CSS 并不存在。而且,页面底部丢失了好玩的HTML5 盾牌。每个问题都可以轻松解决,而功能检测则是明确问题的第一步。两个问题的原因都很简单:对于Internet Explorer 8 来说,、和都不是有效的HTML 元素,所以无法使用。要解决问题,我们不用UA 嗅探来判断所使用的浏览器/版本,而要通过JavaScript 询问浏览器是否支持元素和它的JavaScript API,对Canvas 的功能检测如下所示:

!!document_createElement_x_x('canvas').getContext

复制代码

  这条语句做了好几件事:首先,它使用两个否定(!!)操作符强行将未定义的值显式地设为false;然后,它手动新建一个canvas 元素,并将它加到DOM 中;最后,它调用getContext函数,这是元素的一个新函数,是通过JavaScript 操纵Canvas API 的途径。如果使用IE9,则这条语句会返回true。如果使用IE8,则getContext会返回“undefined”(未定义),会被前面的两个否定操作符强行变为false。
  这是最基本的功能检测。利用这条语句以及其他类似语句,就有了查询浏览器所支持功能的更可靠方法。关于手动功能检测的更多信息,请参阅diveintohtml5.info/everything.html

  三、使用Modernizr进行功能检测
  手动功能检测肯定是对UA 嗅探的提高,但这种做法仍然需要你做大量工作来检测功能是否可用,以及在功能不存在的时候决定做什么。虽然Canvas 示例很简单,只需要一行代码,但不是每个要检测的功能都这么简单——不同浏览器的检测代码也各不相同。例如,要检测是否支持前面使用的CSS3 模块(border-radius 和box-shadow)就有些麻烦。值得庆幸的是,Modernizr (modernizr.com) 提供了更好的方法。Modernizr是一个JavaScript 库“……检测下一代 Web 技术(即源于HTML 5 和CSS3 规范的功能)的本地实现是否可用”。在页面上添加对Modernizr的引用可以提供四大功能:
  1) 全面列出支持的功能,智能地加入标签,从而实现CSS 的条件定义。
  2) 一个 JavaScript 对象,方便进行基于脚本的功能检测。
  3) 在运行的时候将全部HTML5 新标签加入DOM,方便IE8 和之前的IE 浏览器(稍  后就会知道不仅如此)。
  4) 一个脚本加载器,可以根据条件将polyfill加载到页面中。

  本文对第1 项不做进一步介绍,但鼓励你访问modernizr.com 网站,学习这一功能及其余功能的文档。
  上面的第2 项功能,可以将下面的代码:  

!!document_createElement_x_x('canvas').getContext

复制代码

  改为这行代码:

Modernizr.canvas

复制代码

  这行代码会返回一个布尔值,表明页面是否支持Canvas 元素。使用Modernizr比自行执行功能检测的好处是,Modernizr是一个经过良好测试、健壮的、广为采用的库,它已经完成了许多繁重的工作。Twitter、Google、Microsoft 以及无数其他机构和开发人员都在使用Modernizr,你当然也可以使用。在ASP.NET MVC 3 工具更新(2011 年4 月发布)中,Microsoft甚至随新的ASP.NET MVC 应用程序一起配备了Modernizr。当然,我们迄今为止所做的,不过是检测是否支持元素。通过功能检测知道了浏览器是否支持某一功能之后,接下来通常是创建一些条件逻辑,在功能不存在的时候阻止特定代码的执行或者换个路径来执行,例如:

if (Modernizr.canvas) {

// 这里执行canvas 代码。

}

复制代码

  根据附加的浏览器功能是否存在来给网站增加功能,这种做法称为“渐进式增强”,因为体验增强针对的能力更强的浏览器。另一方面是“优雅降级”,即某项功能的缺失不会造成浏览器出错或发生故障,而是应该向用户提供一些削弱的功能或替代能力。对于旧版浏览器来说,不必将优雅降级作为默认选择。在许多情况下,甚至可能不是最佳选择。相反,在Modernizr的帮助下,你通常可以使用许多可用的浏览器polyfill,将类似于HTML5 的功能添加到不支持HTML5 的浏览器中。

  四、什么是Polyfill
  根据Modernizr网站的说法,polyfill是“在旧版浏览器上复制标准API 的JavaScript 补充”。“标准API”指的是HTML5 技术或功能,例如Canvas。“JavaScript 补充”指的是可以动态地加载JavaScript 代码或库,在不支持这些标准API 的浏览器中模拟它们。例如,geolocation(地理位置)polyfill可以在navigator 对象上添加全局的geolocation对象,还能添加getCurrentPosition函数以及“坐标”回调对象,所有这些都是W3C 地理位置API 定义的对象和函数。因为polyfill模拟标准API,所以能够以一种面向所有浏览器未来的方式针对这些API 进行开发,最终目标是:一旦对这些API 的支持变成绝对大多数,则可以方便地去掉polyfill,无需做任何额外工作。
  通过在页面上添加对Modernizr的引用,我就得到了与代码段1 示例相关的polyfill的直接好处。页面显示没有样式,是因为IE8 不认识<article>和<header>标签。因为它不认识这些标签,所以没将它们加入DOM,而CSS 选择元素要发挥样式作用,需要在DOM 中有这些元素。当我在页面上添加<script>标签和对Modernizr的引用时,结果就有了样式,如图3 所示。我之所以得到这个好处,是因为Modernizr用JavaScript(document_createElement_x(‘nav’))手动地将所有HTML5 的新标签添加到DOM,这样CSS 就能选择标签并给标签加上样式。



除了在Internet Explorer 中添加对新的HTML5 元素的支持外,Modernizr库默认不提供任何额外的polyfill。额外的polyfill需要自行提供,或者使用自己的脚本,或者从Modernizr网站上日益增加的选项列表中选择一个。在2.0 版中,Modernizr提供了一个条件脚本加载器(基于yepnope.js—yepnopejs.com),可以帮助你只在需要的时候异步下载polyfill库。使用Modernizr配合一个或多个polyfill库来提供需要的功能,是一个强大的组合。

五、使用Polyfill模拟HTML5 功能
对于Canvas 来说,在Modernizr和JavaScript 库excanvas的帮助下,用polyfill可以在IE8 及之前的版本中实现Canvas 支持,可以在IE6、IE7 和IE8 上添加API 级别的Canvas支持。可以从bit.ly/bSgyNR下载excanvas,将它添加到自己的脚本文件夹,然后在页面的脚本块中添加一些代码,如代码段2 所示。

Modernizr.load({

test: Modernizr.canvas,

nope: '../js/excanvas.js',

complete: function () {

Modernizr.load('../js/html5CanvasLogo.js');

}

}]);

复制代码

代码段3 用Modernizr和PIE 添加CSS3 支持



六、使用Polyfill协助进行优雅降级
除了使用这里讨论的polyfill技术,在希望应用程序优雅降级的地方也可以借助于Modernizr,而不是用另一个库进行填补(polyfill)。
假设网页上有一个Bing Maps 控件,而且我希望使用Geolocation来确定用户当前位置,然后将这个位置作为大头钉放在地图控件上。虽然新版本的浏览器都支持Geolocation,但在旧版浏览器中并不支持。纯粹使用JavaScript 提供完整的Geolocation支持还确实有些麻烦,即使有针对Geolocation的填补(polyfill)
实现起来也不轻松,所以我决定要对自己的应用程序进行优雅降级。当用户的浏览器不支持Geolocation时,我会提供一个表单,用户可以在表单中手动输入位置,我将用用户输入的位置定位和固定地图。
通过Modernizr,只要用一个简单的加载脚本,调用我创建的两个脚本中的一个即可,如代码段4 所示。在这个示例中,我测试的是Modernizr.geolocation属性。如果为true(“yep”分支),就加载fullGeolocation.js 脚本,这个脚本使用Geolocation API 定位(要得到用户许可),并将位置放在地图上,如图5 所示。如果测试为false(“nope”分支),则加载备用脚本,在页面上显示一个地址表单。用户提交表单时,我会使用用户提供的地址将地图居中并固定,如图6 所示。这样,我的页面为最新的浏览器提供了优秀的体验,同时对旧版浏览器提供了降级到合理替代品的优雅方式。

Modernizr.load({

test: Modernizr.geolocation,

yep: '../js/fullGeolocation.js',

nope: '../js/geolocationFallback.js'

});

代码段4 用Modernizr提供优雅降级





  在面对庞大的用户群仍然使用旧版浏览器的时候,很容易认为HTML5 的一些高级功能对你的网站不适用。但是现在已经有了很好的解决方案,不仅能够帮助你优雅地降级,还能提升旧版浏览器的能力,让你的用户立即就能体验到HTML5 的能力。在本文中,你看到了功能检测、Modernizr和polyfill,所以你可以毫不迟疑地采用HTML5,既满足日益增长的使用最新浏览器的用户,又不会丢失使用旧版浏览器的庞大用户群。而我们要做的,不光是让网站适应旧版浏览器,更多的是要让用户更好的体验到网站的内容,如果你想要了解更多内容,可以参考下IE10兼容性白皮书,相信你会获得很多帮助,下载地址:http://vdisk.weibo.com/s/bKgeq
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: