做为新一代的 HTML 标准,HTML5 不只强化了 Web 网页的表现性能,还追加了本地数据库等 Web 应用的功能。虽然 HTML5 标准仍处于完善之中。然而,大部分新版本的浏览器已经可以支持某些 HTML5 的功能了。HTML5 标准所描述的功能很是强大,如:它提供了一些新的元素和属性,例如 <nav>(网站导航块)和 <footer> 等等,这种标签将有利于搜索引擎的索引整理。一样,也加入不少新的 JavaScript 对象和方法,使得咱们能够基于更多的接口 API 开发功能更增强大的 web 应用。这篇文章将重点介绍 HTML5 所带给 web 开发工程师们的各类便利以及它的一些使用技巧。javascript
自 1999 年 12 月发布的 HTML 4.01 后,后继的 HTML5 和其它标准被束之高阁,为了推进 Web 标准化运动的发展,一些公司联合起来,成立了一个叫作 Web 超文本应用技术工做组 - WHATWG 的组织,该组织对 HTML5 的发展起了相当重要的做用。HTML5 草案的前身名为 Web Applications 1.0,於 2004 年被 WHATWG 提出,於 2007 年被 W3C 接纳,成立了新的 HTML 工做团队。HTML5 的第一份正式草案已于 2008 年 1 月 22 日公布,总的来讲有两大特色:首先,强化了 Web 网页的表现性能。其次,追加了本地数据库等 Web 应用的功能。HTML5 即将成为 HTML、XHTML 以及 HTML DOM 的新标准,虽然目前 HTML5 仍处于完善之中,然而,大部分现代浏览器已经具有了某些 HTML5 支持,因此 HTML5 前景一片看好。php
回页首css
HTML5 的最大的特色之一就是提供了不少新的元素,这些元素至关强大,也很是符合咱们平常开发的须要。以前咱们花了很大力气写好的一些控件,如:日期控件,进度条控件等等,已经被 HTML5 支持了。在接下来的章节中,咱们会介绍一些 Web 开发中比较经常使用的新元素,并深刻介绍他们的各类属性和特性。html
HTML5 拥有多个新的表单输入类型。这些新特性提供了更好的输入控制和验证。来看一个简单示例:前端
<input type="email" name="user_email" /> <input type="url" name="user_url" />
这里是一个简单的 email、url 输入框使用示例,可见,咱们只须要设定他的 type 属性便可。若是设定为 email,则浏览器会验证他的输入是否合法(必须为邮件格式),见下图:(支持浏览器 Firefox,Chrome 和 Opera)html5
Email 输入框也支持输入多个,只须要用“,”分隔开来便可,浏览器会对这些分隔开来的字符串分别验证。java
让咱们在深刻一点,如下是浏览器验证所对等的正则表达式:git
“/^[a-zA-Z0-9.!#$%& ’ *+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/”web
这种验证若是有咱们本身来作,会耗费大量时间,并且性能不会太好。值得庆幸的是:随着各大浏览器的不断完善,愈来愈能更好的支持 HTML5,不久的未来,咱们就不用再考虑如何作这些验证了。正则表达式
同理,“url”类型也是。这样一来,节省了大量的验证代码,使用起来极为方便。
再来看数字输入框的例子:
<input type="number" name="points" min="1" max="10" step="1"/> <input type="range" name="points" min="1" max="10" />
这里的 step 表示规定的合法的数字间隔。他们的效果图以下:(支持浏览器 Chrome,Safari 和 Opera)
这些数字输入控件使用方便且很是直观,因为是内置的控件,咱们彻底不用担忧性能的问题,因此,强烈建议你们试用。
接下来咱们再来看两个使用比较普遍的控件 - date 和 time。HTML5 拥有多个可供选取日期和时间的新输入类型:
1. date - 选取日、月、年
2. month - 选取月、年
3. week - 选取周和年
4. time - 选取时间(小时和分钟)
5. datetime - 选取时间、日、月、年(UTC 时间)
6. datetime-local - 选取时间、日、月、年(本地时间)
参见以下示例:
<input type="date" name="user_date" /> <input type="month" name="user_date" /> <input type="time" name="user_date" /> <input type="datetime" name="user_date" />
使用方式依然简单,能够参见以下效果图:(支持浏览器 Chrome,Safari 和 Opera)
如图 3 所示,这里列出了选月(Month)和选时间加日期(DateTime)的效果图。这些都是内置的一些控件,无需咱们额外开发了。除此之外,还有“datatime-local”的类型,专门针对不一样的国家实现本地化,功能至关完善。
还有“search”控件,专门用来做为搜索框出如今页面上,样式与文本框相同。以上这些简单的新输入控件使用便捷且性能颇高。
再来看看稍微复杂一些的控件:数据列表,在 HTML5 中被称做“datalist”,用来显示列表数据,相似一个简单的 select 控件。这个控件简单清晰,方便选择且支持输入,在现在的 Web 开发中愈来愈受到青睐,见以下示例:
<input type="url" list="url_list" name="link" /> <datalist id="url_list"> <option label="W3School" value="http://www.W3School.com.cn" /> <option label="Google" value="http://www.google.com" /> <option label="Microsoft" value="http://www.microsoft.com" /> </datalist>
可见,datalist 控件的用法相似 select,参见以下效果图:(支持浏览器 Firefox,Chrome 和 Opera)
在咱们输入时,他会自动弹出备选项,这种控件很是人性化,用户体验极好。
再来看看 keygen 元素,keygen 元素的做用是提供一种验证用户的可靠方法。keygen 元素是密钥对生成器(key-pair generator)。当提交表单时,会生成两个键,一个是私钥,一个公钥。私钥(private key)存储于客户端,公钥(public key)则被发送到服务器。公钥可用于以后验证用户的客户端证书(client certificate)。
<form action="demo_form.asp" method="get"> Username: <input type="text" name="usr_name" /> Encryption: <keygen name="security" /> <input type="submit" /> </form>
这里咱们加入了一个“name”为“security”的 Keygen 控件,在该表单提交时,浏览器会提示您输入密码以确保提交安全,以下图所示:(支持浏览器 Firefox,Chrome,Safari 和 Opera)
如图 5 所示,点击“submit”时,会弹出“password”对话框。经过很简单的代码,咱们便能实现安全的表单提交。
目前,支持此元素的浏览器很少,不过相信各大浏览器厂商也都想早日完成 HTML5 彻底支持的目标。
最后,咱们来看看 output 元素,该元素很简单,专门用来输出,见以下示例:
function resCalc() { numA=document.getElementById("num_a").value; numB=document.getElementById("num_b").value; document.getElementById("result").value=Number(numA)+Number(numB); } <form onsubmit="return false"> <input id="num_a" /> + <input id="num_b" /> = <output id="result" onforminput="resCalc()"></output> </form>
这里咱们经过“onforminput”监听表单输入事件,经过对 Output 元素“value”属性的赋值来显示输出,代码简洁且通俗易懂。(支持浏览器 Firefox,Chrome,Safari 和 Opera)
前面咱们介绍了新的表单相关元素,接下来咱们来看看新的一些元素属性。HTML5 中提到的新属性很是多,这些属性控制着不少很是实用的功能,如:autocomplete(自动补全)、required(不能为空)、placeholder(提示符)等等,还有 autofocus、list、min、max、pattern、novalidate 等等。下面咱们来一一介绍:
<form action="demo_form.asp" method="get" autocomplete="on"> First name: <input type="text" name="fname" /><br /> Last name: <input type="text" name="lname" /><br /> E-mail: <input type="email" name="email"autocomplete="off"/><br /> <input type="submit" /> </form>
若是咱们设置了“autocomplete”属性为“on”,那么当用户在自动完成域中开始输入时,浏览器会在该域中显示填写的选项。参见图 6:(支持浏览器 IE9,Firefox,Chrome,Safari 和 Opera)
咱们再来看看关于 Form 的几个特殊属性:表单重写属性。表单重写属性(form override attributes)容许您重写 Form 元素的某些属性设定。
表单重写属性以下:
重写后,Form 会按照您重写的后的方案去执行。参考以下代码:
<form action="demo_form.asp" method="get" id="user_form"> E-mail: <input type="email" name="userid" /><br /> <input type="submit" value="Submit" /> <br /> <input type="submit" formaction="demo_admin.asp"value="Submit as admin" /> <br /> <input type="submit"formnovalidate="true"value="Submit without validation" /> <br /> </form>
清单 8 中,咱们就分别重写了 Form 表单的“formaction”和“formnovalidate”属性。在咱们点击“Submit as admin”按钮时,Form 会提交到“demo_admin.asp”,点击“Submit without validation”按钮时,Form 不会作任何校验。(支持浏览器 Firefox,Chrome,Safari 和 Opera)
关于按钮,HTML5 也多了一些处理,好比“image”形式的按钮:
若是咱们经过 Get 方式提交,则 url 参数会变成“user_name=aaa&x=52&y=51”,后面多出来的坐标信息能够用来判断用户的点击区域,以进行不一样的后台处理。
接下来咱们来看看三个比较实用的新属性:Pattern,Placeholder 和 Required。(支持浏览器 Firefox,Chrome,Safari 和 Opera)
Country code: <input type="text" name="country_code" pattern="[A-z]{3}"title="Three letter country code" />
能够看到,这里咱们给输入框定义了 Pattern 为“[A-z]{3}”,也就是包含三个字母的正则表达式约束,若是输入不合法,咱们会看到以下效果:(支持浏览器 Firefox,Chrome 和 Opera)
Pattern 这个属性让咱们不用在经过 JavaScript 来绑定验证了。
再来看看 Placeholder,这个属性主要用来在用户未输入时,提示用户输入的数据的形式或者直接给出输入示例:
当该输入框获取焦点时,提示字符消失。参考以下代码:(支持浏览器 Firefox,Chrome,Safari 和 Opera)
<input type="search" name="user_search" placeholder="Search W3School" />
最后咱们来看看 Required 属性,它主要就是要求用户必须有输入,不然校验不经过。他的代码很简单:
Name: <input type="text" name="usr_name" required="required" />
新的表单元素的相关属性还有不少,咱们这里不一一介绍了,有兴趣的读者能够参考官方文档。(支持浏览器 Firefox,Chrome 和 Opera)
除了新的表单元素,还有不少其余的功能强大的新元素。
<video width="320" height="240" controls="controls"> <source src="movie.ogg" type="video/ogg"> <source src="movie.mp4" type="video/mp4"> Your browser does not support the video tag. </video>
顾名思义,这是用来播放视屏的。这个元素的诞生,意味着咱们不用再使用第三方插件了,不管是从性能仍是从易用性上都大大优于从前。如今 Firefox、Chrome、Opera 等的最新版本都支持 Video 元素,如今主要支持 Ogg 和 MPEG 两种视屏格式。您还可以经过“controls”属性设置是否显示控制按钮,“preload”是否在页面加载时预加载视屏等等。(支持浏览器 IE9,Firefox,Chrome,Safari 和 Opera)
让咱们再了解得深刻一点:事实上,HTML5 的 Video 元素的功能远远不止这些内容。它有不少属性:
这里列举出相对比较实用的一些属性。它总共有 30 多个经常使用的属性功能,感兴趣的读者能够参考 W3C 官方网站进一步了解。
一样,它也有不少实用的方法和事件:
load()、play()、pause() 等等控制着视频的加载,播放和暂停。可监听的事件也是至关丰富:
因为事件种类不少,这里咱们也只能列举出一部分相对比较实用的事件。因而可知,Video 标签是足够强大的,它彻底有能力取代任何一种嵌入式的 Web 媒体播放器插件。
<audio controls="controls"> <source src="song.ogg" type="audio/ogg"> <source src="song.mp3" type="audio/mpeg"> Your browser does not support the audio tag. </audio>
Audio 使用方法与 Video 相似,一样能够设定“controls”、“preload”等等属性。效果图以下:(支持浏览器 IE9,Firefox,Chrome,Safari 和 Opera)
Audio 元素的属性,方法和事件也是很是丰富的。它的这些功能和 Video 很是类似,读者也能够参考 Video 的相关介绍。
接下来咱们来看看 Canvas 元素:(支持浏览器 IE9,Firefox,Chrome,Safari 和 Opera)
<script type="text/javascript"> var c=document.getElementById("myCanvas"); var cxt=c.getContext("2d"); cxt.moveTo(10,10); cxt.lineTo(150,50); cxt.lineTo(10,50); cxt.stroke(); var c=document.getElementById("myCanvas"); var cxt=c.getContext("2d"); cxt.fillStyle="#FF0000"; cxt.beginPath(); cxt.arc(70,18,15,0,Math.PI*2,true); cxt.closePath(); cxt.fill(); </script>
Canvas 用来画矢量图,它提供了不少画矢量图的方法,并且效率很是好。
让咱们深刻剖析一下 Canvas 的功能:
咱们还可以设置线条样式:
接下来是一些更为高级的接口:
因而可知,Canvas 的功能是很是强大的,足以知足各类 Web 矢量图开发的须要。
感兴趣的读者还能够看看 WebGL,如今 Firefox、Chrome、Safari 和 Opera 的新版本基本都支持 WebGL 了(须要在浏览器中开启)。WebGL 定义了一套 API, 可以容许在网页中使用相似于 Open GL 的接口,其实是一套基于 OpenGL ES 2.0 的 3d 图形 API。这些 API 是经过 HTML 5 的 canvas 标签来使用的。WebGL 主要用于 3D 矢量图,有更为强大的矢量图绘制接口。给出一段代码示例:
<canvas id="canvas_object" style="border:1px solid red;" width='600px' height='450px'></canvas> var canvas = document.getElementById( "canvas_object" ); g_WebGLContext = canvas.getContext( "experimental-webgl" ); // setup viewport g_WebGLContext.viewport(0, 0, canvas.width, canvas.height); // set clear color g_WebGLContext.clearColor( 0.0, 0.0, 0.0, 1.0 ); // create shader and data CreateShader(); CreateData(); // main loop setInterval( drawScene, 30 );
如清单 15 所示,WebGL 的代码基于 Canvas,与 Canvas 相关代码相似。WebGL 主要用于 3D 效果的加强,经过 WebGL 每每能够实现出咱们意想不到的 3D 矢量图效果。
接下来咱们来看看新的一些结构布局相关的元素:
如图 11 能够一目了然,这些新的元素(header, nav, section, article, footer 等等)自己其实相似于一个 <div>, 可是他们会有默认的布局方式,用户不用再用 div 加上 css 样式来模拟布局了。除此之外,若是用户在 <section> 标签内加入“contenteditable='true'”的属性,该 <section> 里面的内容即可以编辑了。有需求的读者能够关注一下这里。
再来看看 Details 和 Summary 标签,这两个标签一般配合使用,实现“总结 - 详细”信息的折叠效果:
其代码很简单,以下:(支持浏览器 Chrome)
<details> <summary>Name & Extension:</summary> <p><input type=text name=fn value="Pillar Magazine.pdf"/></p> <p><label><input type=checkbox name=ext checked/>Hide extension</label></p> </details>
它们也能够和 <legend> 标签协同使用,有兴趣的读者能够深刻研究一下。
接下来咱们来看看 Dialog 元素,这里咱们以一段对话为例:
<dt>Role A</dt> <dd>Do you like HTML5?</dd> <dt>Developer</dt> <dd>Yes<dd>
这里,咱们能够把 <dt> 做为说话的人,<dd> 做为说话的内容,其效果以下:
可见,对这些新元素,浏览器的解析更加智能化,为咱们省去了不少样式的工做。
还有一些小标签如 <mark>,主要用于高亮显示一段话中的某些文字,<meter> 用于表示一个范围内的值,示例以下:
<p>your score is : <meter value="88.7" min="0" max="100" low="65" high="96" optimum="100">B+</meter> </p>
其对应的样式以下:(支持浏览器 Chrome 和 Opera)
分两种状况,若是浏览器支持 <meter> 标签,则显示左边样式,不然,显示右边的样式。
一样,还有 <progress> 标签,专门用于显示进度:
<progress value="40" max="100">40%</progress>
有了这些新的元素,咱们不用再像之前那样经过不少 HTML,CSS 和 JavaScript 代码来模拟这样一个控件了。(支持浏览器 Firefox、Chrome 和 Opera)
在来看一个稍微复杂一点的元素:Menu。其实它的使用方式也很是简单,代码以下:
<menu type="toolbar"> <li> <menu label="File" type="popup"> <button type="button" onclick="file_new()">New...</button> <button type="button" onclick="file_open()">Open...</button> <button type="button" onclick="file_save()">Save</button> </menu> </li> <li> <menu label="Edit" type="popup"> <button type="button" onclick="edit_cut()">Copy</button> <button type="button" onclick="edit_copy()">Cut</button> <button type="button" onclick="edit_paste()">Paste</button> </menu> </li> </menu>
这里的 Menu 元素内部的 Button 元素也能够改为 Command 元素,显示效果和 Button 元素相似,同时 Command 也支持 Checkbox,Radio 的形式,只须要设置他的“type”属性便可。(支持浏览器 Opera)
他的效果和不少现有的 Web 控件库里的 Menu 控件差很少,可是他是 Native 的元素,效率会快不少。
HTML5 的新元素还有不少,如 <datagrid>,<figure>,<datatemplate> 等等,这里咱们不一一介绍,有兴趣的读者能够参考 W3C 的官方文档深刻研究。
最后咱们来看几个高级的专题,这些元素可能咱们不多会用到,不过在某些特殊环境或者需求下可能就不必定了,仍是颇有了解一下的必要的。
首先,咱们来看看 <a> 标签中的“rel”属性,它主要用来规定当前文档与目标 URL 之间的关系(仅在 href 属性存在时使用)。先来看一个例子:
<a rel="noreferrer" href="http://www.functravel.com/">Cheap Flights</a>
这里的‘rel="noreferrer"’表示,当用户跟随该超连接(http://www.functravel.com/)时,浏览器不会发送 HTTP referer 头信息。“rel”属性还有不少可设定的值,如“alternate”,“archieve”,“author”,“external”,“index”等等,这里再也不一一介绍。(支持浏览器 IE九、Firefox、Chrome,Safari 和 Opera)
再来看看 HTML5 中的 Microdata Model,它不是一个元素,也不是一个属性,他是一个模型,由一系列相关属性构成,主要用来标识 HTML 文档结构(Document),使其更加容易被计算机理解。若是您在您的 HTML 文档结构中加入了一些 Microdata 的标识描述,您的文档将更加容易被“理解”和搜索到,如 Google 的搜索引擎就能更迅速的搜索您的页面而且在查询结果中更为清晰的给出关于该页面的相关信息。来看这样一个示例:
<div itemscope itemtype="http://data-vocabulary.org/Person"> My name is <span itemprop="name">Bob Smith</span> but people call me <span itemprop="nickname">Smithy</span>. Here is my home page: <a href="http://www.example.com" itemprop="url">www.example.com</a> I live in Albuquerque, NM and work as an <span itemprop="title">engineer</span> at <span itemprop="affiliation">ACME Corp</span>. </div>
这段 HTML 中加入了“itemtype”,“itemprop”等等属性,实际上是用另外一种方式标识该文档结构。Google 引擎爬到该页面时,会解析出全部您的 Microdata 信息,从而更好的展现了该页面的整体内容概览。而不是想普通页面那样的对其内容的一段默认的截取,这段截取的文字每每很难知足咱们的预期。
HTML5 还有一些关于可用性(ARIA)和 Sandbox 的专题,这里再也不深刻,建议有兴趣的读者参考 W3C 官方文档。
这一节咱们重点看看 HTML5 带给咱们那些 JavaScript 经常使用的对象和方法。这些对象和方法可能咱们已经求之不得好久了,如今他们终于来了!
先来了解一下 Storage 吧,主要用于客户端的持久化数据存储,分为三种类型:GlobalStorage、LocalStorage 和 SessionStorage,使用方式很是简单:(支持浏览器 IE8+,Firefox,Chrome,Safari 和 Opera)
globalStorage['developer.mozilla.org'].username = "John"; localStorage.username = "John"; sessionStorage.username = "John"; sessionStorage.setItem("username", "John");
“globalStorage”:不属于标准,Firefox 特有的对象,它能够跨域存取数据。
“localStorage”:主要针对同一个域下面数据的存取。
“sessionStorage”:顾名思义,其生命周期为一个 session,刷新标签页时数据保留,可是当标签页关闭时,sessionStorage 内存储的数据会消失。
以上三种 Storage 用户能够根据本身的须要来选择。
再来看一个“navigator”的“onLine”的属性,咱们能够经过该属性值得知当前浏览器的运行模式:在线仍是离线。(支持浏览器 Firefox 和 Opera)
当咱们选择“Work Offline”时,“onLine”的属性值会置“false”,不然默认为“true”。
再来看几个新的方法。对于“getElementById”、“getElementsByTagName”等等这些定位页面元素的方法想必你们已经很是熟悉了,HTML5 又推出了“getElementsByClassName”,经过 Class 的名称检索元素集。使用方式以下:(支持浏览器 Firefox,Chrome,Safari 和 Opera)
var elements = document.getElementsByClassName('section'); elements[0].focus();
能够看出,其使用方式与“getElementsByTagName”基本无异,返回值同“getElementsByTagName”同样,是 HTMLCollection 类型。
建议你们留意一下“querySelectorAll”方法,这种基于 CSS Selector 检索元素的方法对咱们的平常开发也是十分有帮助的。
var els = document.querySelectorAll("ul li:nth-child(odd)"); var els = document.querySelectorAll("table.test > tr > td");
接下来咱们来看看关于浏览器历史(History)对象的一些新方法。
咱们知道,使用“back()”,“forward()”和“go()”方法能够在用户的历史记录中前进和后退,可是针对 Web2.0 的零页面跳转的需求,HTML5 引入了“histtory.pushState()”和“history.replaceState()”这两个方法。它们容许在无页面跳转的状况下添加和修改 History 实体,即操做浏览器历史,而且改变当前页面的 URL(pushState 用于向 history 添加当前页面的记录,而 replaceState 和 pushState 的用法彻底同样,惟一的区别就是它用于修改当前页面在 history 中的记录)。同时,这些方法还会和“window.onpopstate”事件一块儿工做。咱们来看看下面的示例:(支持浏览器 Firefox、Chrome、Safari 和 Opera)
var stateObj = { myVar: "myValue" }; var stateObj2 = { myVar: "myValue2" }; history.pushState(stateObj, "history page", "hisPage.html"); history.pushState(stateObj, "history page 2", "hisPage2.html"); window.onpopstate = function(e) { console.log(e.state); };
这种方法将会使 URL 地址栏显示“http://yoursiteaddress.com/hisPage.html”,但浏览器不会加载“hisPage.html”页面,即便这个页面存在也不会加载。
若是如今用户继续访问一个新的网址(如 http://sina.com.cn),而后点击浏览器的后退。这时,地址栏将会显示“http://yoursiteaddress.com/hisPage.html”,同时页面会触发“popstate”事件,“stateObj”会从“popstate”事件传入供咱们使用。若是咱们再次点击后退,URL 将变成“http://yoursiteaddress.com/hisPage2.html”,同时页面会再次触发“popstate”事件。可是注意,这两次的回退不会形成页面的刷新。
一样,“onhashchange”事件也值得咱们关注一下,它专门用于响应 URL 的 hash 值的变化,咱们不用再像之前那样轮询地检测 hash 值的变化了。
最后,有兴趣的读者还能够看看“onpageshow”和“onpagehide”,他们对应于“onload”和“onunload”事件。页面加载时默认触发“onload”事件,可是若是页面是从“往返缓存”里面加载的,则触发“onpageshow”等事件。
接下来再来看一个跨域消息传递的使用。HTML5 里面推出了“postMessage”方法用于 Iframe 之间的消息传递,支持跨域传递。这意味着,咱们不用再像之前那样经过 hash 值等等办法实现跨域 Iframe 的消息通信,先看以下示例:
若是咱们要实现如图 19 的功能(这里 iframe一、iframe2 和主界面都是在不一样的域),若是 iframe1 须要发消息给 iframe2,只须要在 iframe1 中取得 iframe2 的对象,调用“postMessage”方法便可,代码参考以下:(支持浏览器 Firefox,Chrome,Safari 和 Opera)
//iframe1 window.parent.frames[1].postMessage(message, 'http://dm1.com'); //iframe2 if (typeof window.addEventListener != 'undefined') { window.addEventListener('message', messageHandler, false); } else if (typeof window.attachEvent != 'undefined') { window.attachEvent('onmessage', messageHandler); } function messageHandler(e){ if(event.origin !== http://dm1.com') return; var data = e.data; ...... }
不难发现,这种作法会即时响应消息,从而让咱们完全摆脱过去轮询机制实现的麻烦。一方“postMessage”,另外一方监听“onmessage”事件,代码很是清晰。
接下来是“Notifications”,又称“桌面提醒接口”,HTML5 的又一新特性,经过这个接口咱们能直接让浏览器发消息到咱们的桌面:
if (window.webkitNotifications) { if (window.webkitNotifications.checkPermission() == 0) { window.webkitNotifications.createNotification("xx.png", "Title", "Body").show(); } else { window.webkitNotifications.requestPermission(); return; } }
可见,使用方法很是简单(createNotification),其效果以下:(支持浏览器 Chrome 和 Safari)
再来看看 HTML5 提供的浏览器缓存的相关接口(ApplicationCache),它能够用来支持离线浏览。
首先,经过“<html manifest="html5demo.manifest" lang="en">” 来引用清单文件,清单文件代码示例以下:
CACHE MANIFEST # 可缓存的文件 CACHE: /favicon.ico index.html stylesheet.css images/logo.png scripts/main.js # 不管是否处于离线状态,对这些资源的全部请求都会绕过缓存。即必须在线访问的文件。可以使用通配符。 NETWORK: login.php /myapi # 没法访问资源时的后备资源 FALLBACK: /main.py /static.html images/large/ images/offline.jpg *.html /offline.html
如上,“index.html”、“stylesheet.css”会自动保存到咱们浏览器的缓存(ApplicationCache)中,当咱们的网络断开时,访问这些文件时,浏览器会直接从缓存中取,让咱们感受像是在在线浏览网页同样。同时,咱们也能够查看当前浏览器缓存的状态,手动更新缓存以及监听缓存相关事件并及时处理:(支持浏览器 Firefox、Chrome、Safari 和 Opera)
// 查看当前浏览器缓存的状态 var appCache = window.applicationCache; switch (appCache.status) { case appCache.UNCACHED: // UNCACHED == 0 return 'UNCACHED'; break; case appCache.IDLE: // IDLE == 1 return 'IDLE'; break; case appCache.CHECKING: // CHECKING == 2 return 'CHECKING'; break; case appCache.DOWNLOADING: // DOWNLOADING == 3 return 'DOWNLOADING'; break; case appCache.UPDATEREADY: // UPDATEREADY == 4 return 'UPDATEREADY'; break; case appCache.OBSOLETE: // OBSOLETE == 5 return 'OBSOLETE'; break; default: return 'UKNOWN CACHE STATUS'; break; }; // 手动更新缓存 var appCache = window.applicationCache; appCache.update(); // 更新缓存 if (appCache.status == window.applicationCache.UPDATEREADY) { appCache.swapCache(); } // 监听缓存相关事件并及时处理 var appCache = window.applicationCache; function logEvent(e) { console.log(e); } function logError(e) { console.log("error " + e); }; appCache.addEventListener('cached', logEvent, false); appCache.addEventListener('checking', logEvent, false); appCache.addEventListener('downloading', logEvent, false); appCache.addEventListener('error', logError, false); appCache.addEventListener('noupdate', logEvent, false); appCache.addEventListener('obsolete', logEvent, false); appCache.addEventListener('progress', logEvent, false); appCache.addEventListener('updateready', function (e) { appCache.swapCache(); window.location.reload(); }, false);
调用“applicationCache.update()”是以编程方式更新缓存,此操做将尝试更新用户的缓存(前提是已更改清单文件)。当 “applicationCache.status”处于 “UPDATEREADY” 状态时,调用“applicationCache.swapCache()”便可将原缓存换成新缓存。这里咱们要注意:这里咱们使用“update()”和“swapCache()”是不会向用户提供更新的资源的。此方法只是让浏览器检查是否有新的清单(html5demo.manifest 是否有变化),下载指定的更新内容以及从新填充应用缓存。
HTML5 中增长了文件操做的接口(FileReader 和 FileWriter),咱们能够直接在 JavaScript 操做文件了:(支持浏览器 Firefox、Chrome 和 Opera)
//e.dataTransfer.files[0] 为文件的 url var file = e.dataTransfer.files[0], reader = new FileReader(); reader.onload = function(event){ holder.style.background = 'url(' + event.target.result + ') no-repeat center'; }; reader.readAsDataURL(file);
这里咱们主要调用“FileReader”的“readAsDataURL”方法读取文件,文件经过流读入完毕后,会回调“FileReader”的“onload”方法,并传入文件流内容(event.target.result),注意,此数据为二进制文件流数据,再也不是文件地址。
一样,FileWriter 的用法也相似:
window.requestFileSystem(window.PERSISTENT, 1024*1024, onInitFs, errorHandler); function onInitFs(fs) { fs.root.getFile('test.txt', {create: false}, function(fileEntry) { // 建立 FileWriter('test.txt') fileEntry.createWriter(function(fileWriter) { fileWriter.seek(fileWriter.length); fileWriter.truncate(1); // 建立一个二进制流对象并写入文件'test.txt'. var bb = new BlobBuilder(); bb.append('Hello World'); fileWriter.write(bb.getBlob('text/plain')); }, errorHandler); }, errorHandler); }
不难看出,文件对象经过“createWriter”构建出“fileWriter”,并经过“fileWriter”的“write”方法写入文件。
这些对象和接口可能不必定很经常使用,可是仍是但愿你们可以关注一下,也许之后在某些特殊的状况下咱们会很是须要他们。
WebSocket 是 HTML5 的又一个使人振奋的功能,它使得咱们的 Web 前端可以和服务器端进行全双工通讯。这是一次 Web 前端通讯机制的飞跃,基本上能够彻底取代咱们以前的长轮询模式。WebSocket 的使用方式很是简单,以下:(支持浏览器 Chrome 和 Safari)
var socket = new WebSocket(location); socket.onopen = function(event) { socket.send(“Hello, WebSocket”); // ”postMessage” } socket.onmessage = function(event) { alert(event.data); } socket.onclose = function(event) { alert(“closed”); }
熟悉 Socket 编程的人可能一看就明白了,其实 WebSocket 的接口与 Java 开发中经常使用的 Socket 的接口很是类似,经过“send”发送请求,“onmessage”来处理返回的消息。WebSocket 对象有三个事件:open,close 和 message。当链接创建时触发 open 事件,当收到消息时触发 message 事件,当 WebSocket 链接关闭时触发 close 事件。同大多数 JavaScript API 同样,事件处理时会调用相应的“onopen”, “onmessage”, 和“onclose”回调函数。
最后咱们来看看 HTML5 支持的地理信息定位,接口很是简单:
<script> function getLocation(){ if (navigator.geolocation) { navigator.geolocation.getCurrentPosition(showPosition); } else { console.log("Geolocation is not supported"); } } function showPosition(position){ console.log("Latitude: " + position.coords.latitude + "<br />Longitude: " + position.coords.longitude); } getLocation(); </script>
很明显,经过“getCurrentPosition”获取地理经纬度信息,经过回调函数“showPosition”基于地理信息做出相应处理,“position”对象里除了“latitude”和“longitude”以外,还有诸如“accuracy”,“altitude”,“speed”等等不少有用的值,但愿你们注意一下。(支持浏览器 IE九、Firefox、Chrome,Safari 和 Opera)
拖拽是 HTML5 中的一个亮点,HTML5 已经能直接支持拖拽功能了,其使用方式也很是简单,参见以下代码:(支持浏览器 IE九、Firefox、Chrome、Safari 和 Opera)
// 便利全部可拖拽的 link var links = document.querySelectorAll('li > a'); ................ // 设置可拖拽属性,非必须 links[i].setAttribute('draggable', 'true'); // 绑定推拽起始事件 , addEvent 是根据浏览器选择 addEventListener 及 attachEvent 等等 addEvent(links[i], 'dragstart', function(e){ e.dataTransfer.effectAllowed = 'copy'; // 设置拖拽传递的数据 e.dataTransfer.setData('Text', this.id); }); // 拖拽释放的容器 var dropContainer = document.querySelector('#dropContainer'); // 监听拖拽事件 addEvent(dropContainer, 'dragover', function(e){ if (e.preventDefault) e.preventDefault(); // allows us to drop this.className = 'over'; ............ }); // 拖入 dropContainer 响应 addEvent(dropContainer, 'dragenter', function(e){ this.className = 'over'; return false; }); // 拖出 dropContainer 响应 addEvent(dropContainer, 'dragleave', function(){ this.className = ''; }); // 拖拽释放事件 addEvent(bin, 'drop', function(e){ // 获取推拽对象 var sourceElement = document.getElementById(e.dataTransfer.getData('Text')); // 进行相关处理 sourceElement.parentNode.removeChild(el); ......... });
不难看出,咱们只须要在开始拖拽时设定好拖拽传递的数据,最后在释放容器里(dropContainer)实现一下拖拽元素释放的处理,整个拖拽功能就算是实现完毕了,整个过程清晰简单明了。HTML5 的拖拽还支持文件,用户能够直接拖拽系统中的文件,释放到页面的释放容器里(dropContainer),能够从“e.dataTransfer.files”变量里获取拖拽的文件进行相关处理。
再来看看 Web Database,关于 Web 的数据库这一特性其实并非 HTML5 标准(规范)的一部分,它是一个独立于 HTML5 以外的一个标准,专门用于定义前端的基于 SQL 语言的数据库操做接口。其实该接口很是简单,主要仍是写 SQL 语句,相信你们应该仍是很熟悉的:(支持浏览器 Chrome、Safari 和 Opera)
<html> <head> <script type="text/javascript"> var db = openDatabase('mydb', '1.0', 'Test DB', 2 * 1024 * 1024); var msg; db.transaction(function(tx){ tx.executeSql('CREATE TABLE IF NOT EXISTS LOGS (id unique, log)'); tx.executeSql('INSERT INTO LOGS (id, log) VALUES (1, "foobar")'); tx.executeSql('INSERT INTO LOGS (id, log) VALUES (2, "logmsg")'); msg = '<p>Log message created and row inserted.</p>'; document.querySelector('#status').innerHTML = msg; }); db.transaction(function(tx){ tx.executeSql('SELECT * FROM LOGS', [], function(tx, results){ var len = results.rows.length, i; msg = "<p>Found rows: " + len + "</p>"; document.querySelector('#status').innerHTML += msg; for (i = 0; i < len; i++) { msg = "<p><b>" + results.rows.item(i).log + "</b></p>"; document.querySelector('#status').innerHTML += msg; } }, null); }); </script> </head> <body> <div id="status" name="status"> Status Message </div> </body> </html>
这里的“openDatabase”接口能够打开已有数据库或者建立一个新的数据库,而后基于“transaction”接口开启事物处理,开始执行相关 SQL 语句(executeSql)。除了建立表,添加记录之外,他也可以检索表记录(results),取得结果并与外界 HTML&JavaScript 作交互。
咱们来详细了解一下他的接口:
打开数据库:
openDatabase( dbName, dbVersion , dbDisplayName , dbEstimatedSize , callbackFun)
如下为参数释义:
打开数据库的事务:
db.transaction(callbackFun,errorCallbackFun,sucessCallbackFun)
在打开数据库之后,就可使用事务 API transaction。每个事务做为操做数据库的原子操做,不会被打断,从而避免了数据冲突。
如下为参数释义:
执行 sql 语句:
executeSql( sqlString, arguments, callbackFun, errorCallbackFun)
此方法为 transaction 的操做,如下为参数释义:
另外,Web Database 也支持索引(index),这能够大大提升咱们的数据库检索性能,咱们能够经过“createIndex”,“openIndex”,“index.get(key)”等方法来使用这些功能。这里咱们不作详细介绍,有兴趣的读者能够参考相关文档。
最后,咱们来了解一下 Web Workers。咱们知道,JavaScript 是单线程运行的,可是有了 Web Workers 以后,JavaScript 也能够多线程了。相似于咱们经常使用的多线程编程,Web Workers 的使用方式至关简单:(支持浏览器 Firefox、Chrome、Safari 和 Opera)
主程序界面 <!DOCTYPE HTML> <html> <head> <title>Worker 示例 </title> </head> <body> <p> 迄今为止最大值为 : <output id="result"></output></p> <script> var worker = new Worker('worker.js'); worker.onmessage = function (event) { document.getElementById('result').textContent = event.data; }; </script> </body> </html> Worker 程序代码(worker.js) var n = 1; search: while (true) { n += 1; for (var i = 2; i <= Math.sqrt(n); i += 1) if (n % i == 0) continue search; postMessage(n); }
因此经过新建 Worker 开启咱们的另外一个 JavaScript“线程”,执行相应脚本,该脚本能够经过“postMessage”与咱们的“主线程”通讯,主线程中经过“onmessage”监听并处理 worker 线程的“postMessage”消息。
为了增强交互性,咱们通常但愿手动启动 worker 线程,实现这种功能只须要稍微修改一下以前的代码:
主程序界面 <!DOCTYPE HTML> <html> <head> <title>Worker 示例 </title> </head> <body> <p> 迄今为止最大值为 : <output id="result"></output></p> <script> var worker = new Worker('worker.js'); worker.onmessage = function (event) { document.getElementById('result').textContent = event.data; }; function worker_start() { worker.postMessage("start"); } </script> <button onclick="worker_start()">Worker Start</button> </body> </html> Worker 程序代码(worker.js) self.addEventListener('message', function(e) { var n = 1; search: while (true) { n += 1; for (var i = 2; i <= Math.sqrt(n); i += 1) if (n % i == 0) continue search; postMessage(n); } }, false);
很简单,这里咱们只须要在主程序界面上让“worker”调用一下“postMessage”,而后在“worker”代码中监听“self.addEventListener('message', function(e) {......}”该消息便可。这就是当今的关于 JavaScript 的多线程解决方案。注意,这里只建立了一个额外线程,用户能够根据本身的需求建立更多的线程。
此外,还有 Shared Web Workers,顾名思义是一种可共享的 Web Workers,同一个域下面的不一样的 JavaScript 脚本都可访问同一个 Shared Web Workers,其使用方式与普通 Web Workers 不一样,它是经过“port”来创建链接(connection)和监听消息,同一个 Shared Web Workers 能够创建多个链接,同时与多个页面协同工做:
主程序界面 <!DOCTYPE HTML> <title>Shared workers 示例 </title> <pre id="log">Log:</pre> <script> var worker = new SharedWorker('shared_work.js'); var log = document.getElementById('log'); worker.port.addEventListener('message', function(e) { log.textContent += '\n' + e.data; }, false); worker.port.start(); worker.port.postMessage('ping'); </script> <iframe src="inner.html"></iframe> 副界面(inner.html) <!DOCTYPE HTML> <title>Shared workers 示例 inner frame</title> <pre id=log>Inner log:</pre> <script> var worker = new SharedWorker('shared_work.js'); var log = document.getElementById('log'); worker.port.onmessage = function(e) { log.textContent += '\n' + e.data; } </script> Worker 程序代码(shared_work.js) var count = 0; onconnect = function(e) { count += 1; var port = e.ports[0]; port.postMessage('Hello World! You are connection #' + count); port.onmessage = function(e) { port.postMessage('pong'); } }
细心的读者会发现,这里咱们分别在两个不一样页面构建了同一个“SharedWorker”(shared_work.js),因此在 Worker 的程序代码中,count 值为 2,即它记录了这两个链接。每次创建链接时,他都会发消息回去(“Hello World......”),并同时构建罅隙监听器,监听来自这两个页面的“postMessage”消息,接受到消息后,会以“pong”回应。Shared Web Workers 自己还有不少内容,这里再也不深刻,有兴趣的读者能够参考 W3C 官方文档。
这篇文章介绍了 HTML5 中各类新元素,新属性,新 JavaScript 接口以及一些复杂的新特性,从基本的新表单元素入手,扩展到新的页面元素,而后引入一些高级专题,由浅入深地介绍了 HTML5 中的各类对象和接口,如 WebSocket 对象、FileReader 对象以及 ApplicationCache 对象等等。最后,介绍了 HTML5 相关的 DND、Web Database 和 Web Worker 复杂新特性。这些新元素,新接口和新特性对咱们的平常开发都颇有帮助,建议你们平时能够多关注一下。
http://www.ibm.com/developerworks/cn/web/1212_zhouxiang_deepintohtml5/index.html