做爲新一代的 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