h5新特性

Posted 杨亚男

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了h5新特性相关的知识,希望对你有一定的参考价值。

CSDN博客

img Gane_Cheng

html5新特性浅谈

发表于2016/10/17 21:25:58  7809人阅读

分类: 前端

这里写图片描述

转载请注明出处:

http://blog.csdn.net/gane_cheng/article/details/52819118

http://www.ganecheng.tech/blog/52819118.html (浏览效果更好)

2014年10月29日,W3C宣布,经过接近8年的艰苦努力,HTML5标准规范终于制定完成。

HTML5将会取代1999年制定的HTML 4.01、XHTML 1.0标准,以期能在互联网应用迅速发展的时候,使网络标准达到符合当代的网络需求,为桌面和移动平台带来无缝衔接的丰富内容。

作为2010年入坑IT的程序员来说,可以说一步一步见证着HTML5的发展。这些年为了兼容IE6放弃了很多HTML5的新特性。但是今时不同以往,移动设备的流行,天然支持HTML5,以及桌面端IE最终被用户和微软唾弃,更多支持HTML5浏览器的受欢迎,我要重新研究一下HTML5带来的这些新特性。

HTML5 的新特性

① 语义特性(Semantic)

HTML5赋予网页更好的意义和结构。

② 本地存储特性(OFFLINE & STORAGE)

基于HTML5开发的网页APP拥有更短的启动时间,更快的联网速度,这些全得益于HTML5 APP Cache,以及本地存储功能。

③ 设备访问特性 (DEVICE ACCESS)

从Geolocation功能的API文档公开以来,HTML5为网页应用开发者们提供了更多功能上的优化选择,带来了更多体验功能的优势。HTML5提供了前所未有的数据与应用接入开放接口。使外部应用可以直接与浏览器内部的数据直接相连,例如视频影音可直接与microphones及摄像头相联。

④ 连接特性(CONNECTIVITY)

更有效的连接工作效率,使得基于页面的实时聊天,更快速的网页游戏体验,更优化的在线交流得到了实现。HTML5拥有更有效的服务器推送技术,Server-Sent Event和WebSockets就是其中的两个特性,这两个特性能够帮助我们实现服务器将数据“推送”到客户端的功能。

⑤ 网页多媒体特性(MULTIMEDIA)

支持网页端的Audio、Video等多媒体功能, 与网站自带的APPS,摄像头,影音功能相得益彰。

⑥ 三维、图形及特效特性(3D, Graphics & Effects)

基于SVG、Canvas、WebGL及CSS3的3D功能,用户会惊叹于在浏览器中,所呈现的惊人视觉效果。

⑦ 性能与集成特性(Performance & Integration)

没有用户会永远等待你的Loading——HTML5会通过XMLHttpRequest2等技术,解决以前的跨域等问题,帮助您的Web应用和网站在多样化的环境中更快速的工作。


下面分别对这七个新特性进行研究。

① 语义特性(Semantic)

这里写图片描述

HTML5增加了新的内容标签,这些标签带有一定的语义,使搜索引擎爬取你的网站信息更高效。

这里写图片描述

HTML4中的内容标签级别相同,无法区分各部分内容。而HTML5中的内容标签互相独立,级别不同,搜索引擎以及统计软件等均可快速识别各部分内容。

这些标签在新闻类网站,博客类网站很有用。

最大的问题就是当使用这些新的语义元素时,那些不支持的浏览器如何处理这些元素。

见过的最多的解决方法是这样的。

<section class="section">

    <!-- content --> 

</section>
  • 1
  • 2
  • 3
  • 4
  • 5
.section 
{
     color: blue;
}
  • 1
  • 2
  • 3
  • 4

如果还想了解更多语义标签兼容性问题,可以参考这篇文章http://html5.group.iteye.com/group/wiki/3293-html5

② 本地存储特性(OFFLINE & STORAGE)

这里写图片描述

HTML5提供了网页存储的API,方便Web应用的离线使用。除此之外,新的API相对于cookie也有着高安全性,高效率,更大空间等优点。

先看W3C对离线存储的介绍。

Web Apps can start faster and work even if there is no internet connection, thanks to the HTML5 App Cache, as well as the Local Storage, Indexed DB, and the File API specifications.

HTML5离线存储包含 应用程序缓存本地存储索引数据库文件接口

下面依次展开介绍。

(1)应用程序缓存(Application Cache)

这里写图片描述

使用 HTML5,通过创建 cache manifest 文件,可以轻松地创建 web 应用的离线版本。

HTML5引入了应用程序缓存,这意味着 web 应用可进行缓存,并可在没有因特网连接时进行访问。

应用程序缓存为应用带来三个优势:

  • 离线浏览 – 用户可在应用离线时使用它们
  • 速度 – 已缓存资源加载得更快
  • 减少服务器负载 – 浏览器将只从服务器下载更新过或更改过的资源。

甭废话,先来感受一下Application Cache的魅力。Shut up,show me the demo!

Demo链接:http://www.ganecheng.tech/welcome_offline.html

1.打开这个网页,第一次等待加载完成之后,页面和普通的网页没有区别。

2.点击刷新按钮,或者强制刷新按钮,看一下第二次打开的速度。有没有快到爆。(速度

3.现在我要求你拔掉网线,断开WiFi,再次点击刷新按钮,或者强制刷新按钮,看一下第三次打开的速度。有没有快到爆。注意,现在并没有联网,和服务器失去连接,依然秒开网页,还能正常操作网页。(离线浏览,减少服务器负载

看完了效果,看一下App Cache的原理。

这里写图片描述

当我们第一次正确配置cache manifest后,浏览器会将清单文件中的资源缓存下来。当我们再次访问该应用时,浏览器会直接返回缓存中的资源,然后检查manifest文件是否有变动,如果有变动就会把相应的变动更新下来,同时改变浏览器里面的app cache。

使用方法

页面声明使用App Cache

 <!DOCTYPE HTML> 
 <html manifest="index.manifest"> 
  • 1
  • 2

清单文件中写明资源。

CACHE MANIFEST
theme.css 
logo.gif 
main.js

NETWORK:
login.asp

FALLBACK:
/html5/ /404.html
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

manifest 文件可分为三个部分:

CACHE MANIFEST - 在此标题下列出的文件将在首次下载后进行缓存
NETWORK - 在此标题下列出的文件需要与服务器的连接,且不会被缓存
FALLBACK - 在此标题下列出的文件规定当页面无法访问时的回退页面(比如 404 页面)

CACHE MANIFEST,是必需的
NETWORK 规定文件 “login.asp” 永远不会被缓存,且离线时是不可用的
FALLBACK 规定如果无法建立因特网连接,则用 “404.html” 替代 /html5/ 目录中的所有文件

一旦应用被缓存,它就会保持缓存直到发生下列情况:

  • 用户清空浏览器缓存 ,用户怎么做,页面左右不了,说了等于没说。
  • manifest 文件被修改,请注意:更新清单中列出的某个文件并不意味着浏览器会重新缓存该资源。清单文件本身必须进行更改,一般是加一个注释,注释的内容是日期,想更新了,改一下日期。
  • 由程序来更新应用缓存,这个稍微靠谱一点。

需要注意的是,更新后的资源需要下次打开页面才能生效,本次打开的页面在更新资源之前就已经从缓存中拿到资源并加载完毕了。

由程序来更新,需要依赖manifest文件被修改这一条,因为调用的是浏览器提供的接口,检测 window.applicationCache.status 的值,如果是 UPDATEREADY,说明浏览器比较manifest文件完毕,可以更新缓存了。window.applicationCache.swapCache()。更新完了,不会立即生效,window.location.reload();重新加载一下页面。

缓存有这么多状态。

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; 
}; 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

程序更新缓存的方法。

// Check if a new cache is available on page load. 
window.addEventListener(\'load\', function(e) 
{ 
    window.applicationCache.addEventListener(\'updateready\', function(e) 
    { 
        if (window.applicationCache.status == window.applicationCache.UPDATEREADY) 
        { 
            // Browser downloaded a new app cache. 
            // Swap it in and reload the page to get the new hotness. 
            window.applicationCache.swapCache(); 
            if (confirm(\'A new version of this site is available. Load it?\')) 
            { 
                window.location.reload(); 
            } 
        } 
        else 
        { 
            // Manifest didn\'t changed. Nothing new to server. 
        }                                                                                       
    }, false); 
}, false); 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

更多更新缓存的方法,可以参考这篇文章:http://www.jb51.net/html5/67850.html

总的来说,App Cache的三个优点非常明显。但是有几个坑,却会导致没人愿意使用这个新特性。

1.使用了App Cache的页面在清单文件更新之后去更新页面资源,但是只在下次打开页面才能生效,这意味着,我们需要使用代码判断是不是最新版本,不是的话,刷新一次页面。这种体验很不好。

2.使用了App Cache的页面也会被缓存,这对于需要动态更新的页面来说,几乎是个噩梦。用户访问到的页面不是最新的,会导致非常多的问题。

3.App cache与browser cache混合在一起会使更新机制变得更加复杂,主要有以下几个因素:
1) App cache在各浏览器平台实现上存在差异;
2) 各浏览器又提供了不同的页面刷新机制;
3) app cache还与传统的browser cache有着千丝万缕的联系;对于它俩如何协同工作,HTML5的相关规范没有对app cache的细节给出非常明确的规定; 浏览器官方文档有没有给出非常明确的说明。
4) browser cache的更新机制本身就已经很复杂。
5) 如果manifest文件本身就有缓存时间,或设置为永远都可用,那你的网页永远都不会被更新了。

App Cache更多的坑,可以参考这篇文章:http://dreclo.blog.163.com/blog/static/528789512014111675023409/ , 然后再决定要不要使用这一新特性。

从惊叹于App Cache的强大,到填坑,W3C花了这么长时间,就弄出来这么个东西,真是令人失望。学会使用App Cache只用了不到一小时,填坑填了一下午。每个页面都要有manifest,每个页面都要加代码去判断去更新缓存,我可以骂人吗。


(2)本地存储(Local Storage)

这里写图片描述

本地存储发展历史.

这里写图片描述

最早的Cookies自然是大家都知道,问题主要就是太小,大概也就4KB的样子,而且IE6只支持每个域名20个cookies,太少了。优势就是大家都支持,而且支持得还蛮好。很早以前那些禁用cookies的用户也都慢慢的不存在了,就好像以前禁用javascript的用户不存在了一样。

userData是IE的东西,垃圾。现在用的最多的是Flash吧,空间是Cookie的25倍,基本够用。再之后Google推出了Gears,虽然没有限制,但不爽的地方就是要装额外的插件(没具体研究过)。到了HTML5把这些都统一了,官方建议是每个网站5MB,非常大了,就存些字符串,足够了。比较诡异的是居然所有支持的浏览器目前都采用的5MB,尽管有一些浏览器可以让用户设置,但对于网页制作者来说,目前的形势就5MB来考虑是比较妥当的。

首先自然是检测浏览器是否支持本地存储。在HTML5中,本地存储是一个window的属性,包括localStorage和sessionStorage,从名字应该可以很清楚的辨认二者的区别,前者是一直存在本地的,后者只是伴随着session,窗口一旦关闭就没了。二者用法完全相同,这里以localStorage为例。

if(window.localStorage)
{
     alert(\'This browser supports localStorage\');
}
else
{
     alert(\'This browser does NOT support localStorage\');
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

存储数据的方法就是直接给window.localStorage添加一个属性,例如:window.localStorage.a 或者 window.localStorage[“a”]。它的读取、写、删除操作方法很简单,是以键值对的方式存在的,如下:

localStorage.a = 3;//设置a为"3"
localStorage["a"] = "sfsf";//设置a为"sfsf",覆盖上面的值
localStorage.setItem("b","isaac");//设置b为"isaac"
var a1 = localStorage["a"];//获取a的值
var a2 = localStorage.a;//获取a的值
var b = localStorage.getItem("b");//获取b的值
localStorage.removeItem("c");//清除c的值
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

这里最推荐使用的自然是getItem()和setItem(),清除键值对使用removeItem()。如果希望一次性清除所有的键值对,可以使用clear()。另外,HTML5还提供了一个key()方法,可以在不知道有哪些键值的时候使用,如下:

var storage = window.localStorage;
function showStorage()
{
     for(var i=0;i<storage.length;i++)
     {
          //key(i)获得相应的键,再用getItem()方法获得对应的值
          document.write(storage.key(i)+ " : " + storage.getItem(storage.key(i)) + "<br>");
     }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

写一个最简单的,利用本地存储的计数器:

    var storage = window.localStorage;
    if (!storage.getItem("pageLoadCount")) 
    {
        storage.setItem("pageLoadCount",0);
    }
    storage.pageLoadCount = parseInt(storage.getItem("pageLoadCount")) + 1;//必须格式转换
    document.getElementById("count").innerHTML = storage.pageLoadCount;
    showStorage();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

不断刷新就能看到数字在一点点上涨,如下图所示:

这里写图片描述

需要注意的是,HTML5本地存储只能存字符串,任何格式存储的时候都会被自动转为字符串,所以读取的时候,需要自己进行类型的转换。这也就是上一段代码中parseInt必须要使用的原因。

想要对localStorage了解更多请参考这篇文章:http://www.cnblogs.com/xiaowei0705/archive/2011/04/19/2021372.html

(3)索引数据库(Indexed DB)

这里写图片描述

从本质上说,IndexedDB允许用户在浏览器中保存大量的数据。任何需要发送大量数据的应用都可以得益于这个特性,可以把数据存储在用户的浏览器端。当前这只是IndexedDB的其中一项功能,IndexedDB也提供了强大的基于索引的搜索api功能以获得用户所需要的数据。

用户可能会问:IndexedDB是和其他以前的存储机制(如cookie,session)有什么不同?

Cookies是最常用的浏览器端保存数据的机制,但其保存数据的大小有限制并且有隐私问题。Cookies并且会在每个请求中来回发送数据,完全没办法发挥客户端数据存储的优势。

再来看下Local Storage本地存储机制的特点。Local Storage在HTML 5中有不错的支持,但就总的存储量而言依然是有所限制的。Local Storage并不提供真正的“检索API”,本地存储的数据只是通过键值对去访问。Local Storage对于一些特定的需要存储数据的场景是很适合的,例如,用户的喜好习惯,而IndexedDB则更适合存储如广告等数据(它更象一个真正的数据库)。

一般来说,有两种不同类型的数据库:关系型和文档型(也称为NoSQL或对象)。关系数据库如SQL Server,mysql,Oracle的数据存储在表中。文档数据库如MongoDB,CouchDB,Redis将数据集作为个体对象存储。IndexedDB是一个文档数据库,它在完全内置于浏览器中的一个沙盒环境中(强制依照(浏览器)同源策略)。

对数据库的每次操作,描述为通过一个请求打开数据库,访问一个object store,再继续。

打开数据库的请求生命周期

这里写图片描述

IndexedDB是否适合我的应用程序?

现在最关键的问题:“IndexedDB是否适合我的应用程序?“像往常一样,答案是肯定的:“视情况而定。“首先当你试图在客户端保存数据时,你会考虑HTML5本地存储。本地存储得到广泛浏览器的支持,有非常易于使用的API。简单有其优势,但其劣势是无法支持复杂的搜索策略,存储大量的数据,并提供事务支持。

IndexedDB是一个数据库。所以,当你想为客户端做出决定,考虑你如何在服务端选择一个持久化介质的数据库。你可能会问自己一些问题来帮助决定客户端数据库是否适合您的应用程序,包括:

  • 你的用户通过浏览器访问您的应用程序,(浏览器)支持IndexedDB API吗 ?
  • 你需要存储大量的数据在客户端?
  • 你需要在一个大型的数据集合中快速定位单个数据点?
  • 你的架构在客户端需要事务支持吗?

    如果你对其中的任何问题回答了“是的”,很有可能,IndexedDB是你的应用程序的一个很好的候选。

IndexedDB用法

现在,你已经有机会熟悉了一些的整体概念,下一步是开始实现基于IndexedDB的应用程序。第一个步骤需要统一IndexedDB在不同浏览器的实现。您可以很容易地添加各种厂商特性的选项的检查,同时在window对象上把它们设置为官方对象相同的名称。下面的清单展示了window.indexedDB,window.IDBTransaction,window.IDBKeyRange的最终结果是如何都被更新,它们被设置为相应的浏览器的特定实现。

        window.indexedDB = window.indexedDB ||
                           window.mozIndexedDB ||
                           window.webkitIndexedDB ||
                           window.msIndexedDB;

        window.IDBTransaction = window.IDBTransaction ||
                           window.webkitIDBTransaction ||
                           window.msIDBTransaction;

        window.IDBKeyRange = window.IDBKeyRange ||
                           window.webkitIDBKeyRange ||
                           window.msIDBKeyRange;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

现在,每个数据库相关的全局对象持有正确的版本,应用程序可以准备使用IndexedDB开始工作。

打开数据库

// 打开我们的数据库,数据库名称,版本号
var request = indexedDB.open("MyTestDatabase", 3);
  • 1
  • 2

indexedDB的三个事件

//数据库打开成功执行
request.onsuccess = function (event) 
{
      // Better use "this" than "req" to get the result to avoid problems with
      // garbage collection.
      // db = request.result;
      db = this.result;
      console.debug("initDb DONE");
};
//数据库打开失败执行
request.onerror = function (event) 
{
      console.error("initDb:", evt.target.errorCode);
};
//在数据库第一次被打开时或者当指定的版本号高于当前被持久化的数据库的版本号时,触发此事件,可以在这个地方创建对象存储空间结构,更新结构,加索引等.
request.onupgradeneeded = function (event) 
{
      console.debug("initDb.onupgradeneeded");
      var store = event.currentTarget.result.createObjectStore(
        DB_STORE_NAME, { keyPath: \'id\', autoIncrement: true });
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

添加数据或更新数据

// 我们的客户数据看起来像这样。
const customerData = [
  { ssn: "444-44-4444", name: "Bill", age: 35, email: "bill@company.com" },
  { ssn: "555-55-5555", name: "Donna", age: 32, email: "donna@home.org" }
];

var transaction = db.transaction(["customers"], "readwrite");

// 当所有的数据都被增加到数据库时执行一些操作
transaction.oncomplete = function(event) {
  alert("All done!");
};

transaction.onerror = function(event) {
  // 不要忘记进行错误处理!
};

var objectStore = transaction.objectStore("customers");
for (var i in customerData) 
{
  var request = objectStore.add(customerData[i]);
  request.onsuccess = function(event) 
  {
    // event.target.result == customerData[i].ssn
  };
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

删除数据

var request = db.transaction(["customers"], "readwrite")
                .objectStore("customers")
                .delete("444-44-4444");
request.onsuccess = function(event) {
  // 删除数据成功!
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

获取数据

var transaction = db.transaction(["customers"]);
var objectStore = transaction.objectStore("customers");
var request = objectStore.get("444-44-4444");
request.onerror = function(event) 
{
  // 错误处理!
};
request.onsuccess = function(event) 
{
  // 对 request.result 做些操作!
  alert("Name for SSN 444-44-4444 is " + request.result.name);
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

对于一个“简单”的提取这里的代码有点多了。下面看我们怎么把它再缩短一点,假设你在数据库的级别上来进行的错误处理:

db.transaction("customers").objectStore("customers").get("444-44-4444").onsuccess = function(event) 
{
  alert("Name for SSN 444-44-4444 is " + event.target.result.name);
};
  • 1
  • 2
  • 3
  • 4

使用游标获取数据

使用 get() 要求你知道你想要检索哪一个键。如果你想要遍历对象存储空间中的所有值,那么你可以使用游标。看起来会像下面这样:

var customers = [];

var objectStore = db.transaction("customers").objectStore("customers");

objectStore.openCursor().onsuccess = function(event) 
{
  var cursor = event.target.result;
  if (cursor) 
  {
    customers.push(cursor.value);
    cursor.continue();
  }
  else 
  {
    alert("Got all customers: " + customers);
  }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

这里有一个封装好的完整的例子,简化了这些操作。

<script type="text/javascript">

        window.indexedDB = window.indexedDB ||
                           window.mozIndexedDB ||
                           window.webkitIndexedDB ||
                           window.msIndexedDB;

        window.IDBTransaction = window.IDBTransaction ||
                           window.webkitIDBTransaction ||
                           window.msIDBTransaction;

        window.IDBKeyRange = window.IDBKeyRange ||
                           window.webkitIDBKeyRange ||
                           window.msIDBKeyRange;

        (function(window){

            \'use strict\';

            var db = {

                version: 1, // important: only use whole numbers!

                objectStoreName: \'tasks\',

                instance: {},

                upgrade: function (e) {

                    var
                        _db = e.target.result,
                        names = _db.objectStoreNames,
                        name = db.objectStoreName;

                    if (!names.contains(name)) {

                        _db.createObjectStore(
                            name,
                            {
                                keyPath: \'id\',
                                autoIncrement: true
                            });
                    }
                },

                errorHandler: function (error) {
                    window.alert(\'error: \' + error.target.code);
                    debugger;
                },

                open: function (callback) {

                    var request = window.indexedDB.open(
                        db.objectStoreName, db.version);

                    request.onerror = db.errorHandler;

                    request.onupgradeneeded = db.upgrade;

                    request.onsuccess = function (e) {

                        db.instance = request.result;

                        db.instance.onerror =
                            db.errorHandler;

                        callback();
                    };
                },

                getObjectStore: function (mode) {

                    var txn, store;

                    mode = mode || \'readonly\';

                    txn = db.instance.transaction(
                        [db.objectStoreName], mode);

                    store = txn.objectStore(
                        db.objectStoreName);

                    return store;
                },

                save: function (data, callback) {

                    db.open(function () {

                        var store, request,
                            mode = \'readwrite\';

                        store = db.getObjectStore(mode),

                        request = data.id ?
                            store.put(data) :
                            store.add(data);

                        request.onsuccess = callback;
                    });
                },

                getAll: function (callback) {

                    db.open(function () {

                        var
                            store = db.getObjectStore(),
                            cursor = store.openCursor(),
                            data = [];

                        cursor.onsuccess = function (e) {

                            var result = e.target.result;

                            if (result &&
                                result !== null) {

                                data.push(result.value);
                                result.continue();

                            } else {

                                callback(data);
                            }
                        };

                    });
                },

                get: function (id, callback) {

                    id = parseInt(id);

                    db.open(function () {

                        var
                            store = db.getObjectStore(),
                            request = store.get(id);

                        request.onsuccess = function (e){
                            callback(e.target.result);
                        };
                    });
                },

                \'delete\': function (id, callback) {

                    id = parseInt(id);

                    db.open(function () {

                        var
                            mode = \'readwrite\',
                            store, request;

                        store = db.getObjectStore(mode);

                        request = store.delete(id);

                        request.onsuccess = callback;
                    });
                },

                deleteAll: function (callback) {

                    db.open(function () {

                        var mode, store, request;

                        mode = \'readwrite\';
                        store = db.getObjectStore(mode);
                        request = store.clear();

                        request.onsuccess = callback;
                    });

                }
            };

            window.app = window.app || {};
            window.app.db = db;

        }(window));


        //将数据显示在页面上的方法
        var bindData = function (data) {

            $("#IndexedDB").html(\'\');

            if(data.length === 0){
                $("#IndexedDB").html("没有数据");
                return;
            }

            data.forEach(function (note) {
                $("#IndexedDB").append(note.id+","+note.title+","+note.text);
            });
        };

        //一个新数据
        var note = 
        {
                id:1,
                title: "数据1",
                text: "数据1的另一个字段"
        };
        //又一个新数据
        var note2 = 
        {
                id:2,
                title: "数据2",
                text: "数据2的另一个字段"
        };
        //插入或更新数据(insert or update)
        window.app.db.save(note,function()
        {
            //window.app.db.getAll(bindData);
        });
        window.app.db.save(note2);

        //获取数据
        window.app.db.get(1,function(item)
        {
            //alert("window.app.db.get:"+item.id+","+item.title+","+item.text);
        });

        //删除数据
        window.app.db.delete(1,function()
        {
            //alert("window.app.db.get:"+item.id+","+item.title+","+item.text);
        }); 

        //删除所有
        window.app.db.deleteAll(function()
        {
            //alert("window.app.db.get:"+item.id+","+item.title+","+item.text);
        });

</script>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241

想对IndexedDB更多用法进行了解的可以参考这两篇文章。

https://developer.mozilla.org/zh-CN/docs/Web/API/IndexedDB_API/Using_IndexedDB

http://web.jobbole.com/81793/


除了IndexedDB以外,还有一种已经被W3C放弃的Web SQL。

浏览器支持本地数据库并不是从IndexedDB才开始实现,它是在Web SQL实现之后的一种新方法。类似IndexedDB,Web SQL是一个客户端数据库,但它作为一个关系数据库的实现,使用结构化查询语言(SQL)与数据库通信。Web SQL的历史充满了曲折,但底线是没有主流的浏览器厂商对Web SQL继续支持。

如果Web SQL实际上是一个废弃的技术,为什么还要提它呢?有趣的是,Web SQL在浏览器里得到稳固的支持。Chrome, Safari, ios Safari, and android 浏览器都支持。另外,并不是这些浏览器的最新版本才提供支持,许多这些最新最好的浏览器之前的版本也可以支持。有趣的是,如果你为Web SQL添加支持来支持IndexedDB,你突然发现,许多浏览器厂商和版本成为支持浏览器内置数据库的某种化身。

因此,如果您的应用程序真正需要一个客户端数据库,你想要达到的最高级别的采用可能,当IndexedDB不可用时,也许您的应用程序可能看起来需要选择使用Web SQL来支持客户端数据架构。虽然文档数据库和关系数据库管理数据有鲜明的差别,但只要你有正确的抽象,就可以使用本地数据库构建一个应用程序。

Web SQL的用法类似于操作SQLite数据库,在这里不展开介绍了。
想对Web SQL了解更多,可以参考这篇文章:http://www.ibm.com/developerworks/cn/web/1210_jiangjj_html5db/

(4)文件接口(File API)

这里写图片描述

在之前我们操作本地文件都是使用flash、silverlight或者第三方的activeX插件等技术,由于使用了这些技术后就很难进行跨平台、或者跨浏览器、跨设备等情况下实现统一的表现,从另外一个角度来说就是让我们的web应用依赖了第三方的插件,而不是很独立,不够通用。在HTML5标准中,默认提供了操作文件的API让这一切直接标准化。有了操作文件的API,让我们的Web应用可以很轻松的通过JS来控制文件的读取、写入、文件夹、文件等一系列的操作。

先看一个demo。之前我们操作一个图片文件,都是先将图片上传到服务器端,然后再使用一个img标签指向到服务器的url地址,然后再进行一个使用第三方插件进行图片处理,而现在这一切都不需要服务器端了,因为FileReader对象提供的几个读取文件的方法变得异常简单,而且全部是客户端js的操作。

http://html5demos.com/file-api/

现在我们自己来使用这些API。

先写好我们的HTML页面。

    <input type="file" multiple="multiple" name="fileDemo" id="fileDemo" />
    <br />
    <input type="button" value="获取文件的名字" id="btnGetFile" />
    <input type="button" value="readAsDataURL" id="readAsDataURL" onclick="showDataByURL();" />
    <input type="button" value="readAsBinaryString" id="readAsBinaryString" onclick="showDataByBinaryString();" />
    <input type="button" value="readAsText" id="readAsText" onclick="showDataByText();" />
    <div id="result"></div>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

获取文件名

            $("#btnGetFile").click(function(e)
            {
                var fileList = document.getElementById("fileDemo").files;
                for (var i = 0; i < fileList.length; i++)
                {
                    if (!(/image\\/\\w+/.test(fileList[i].type)))
                    {
                        $("#result").append("<span>type:" + fileList[i].type + "--******非图片类型*****--name:" + fileList[i].name + "--size:" + fileList[i].size + "</span><br />");
                    }
                    else
                    {
                        $("#result").append("<span>type:" + fileList[i].type + "--name:" + fileList[i].name + "--size:" + fileList[i].size + "</span><br />");
                    }
                }
            });
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

readAsDataURL()

开始读取指定的Blob对象或File对象中的内容. 当读取操作完成时,readyState属性的值会成为DONE,如果设置了onloadend事件处理程序,则调用之.同时,result属性中将包含一个data: URL格式的字符串以表示所读取文件的内容.

这个方法很有用,比如,可以实现图片的本地预览.

        function showDataByURL()
        {
            var resultFile = document.getElementById("fileDemo").files[0];
            if (resultFile)
            {
                var reader = new FileReader();

                reader.readAsDataURL(resultFile);
                reader.onload = function(e)
                {
                    var urlData = this.result;
                    document.getElementById("result").innerHTML += "<img src=\'" + urlData + "\' alt=\'" + resultFile.name + "\' />";
                };

            }

        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

readAsBinaryString()

开始读取指定的Blob对象或File对象中的内容. 当读取操作完成时,readyState属性的值会成为DONE,如果设置了onloadend事件处理程序,则调用之.同时,result属性中将包含所读取文件的原始二进制数据.


        function showDataByBinaryString()
        {
            var resultFile = document.getElementById("fileDemo").files[0];
            if (resultFile)
            {
                var reader = new FileReader();
                //异步方式,不会影响主线程
                reader.readAsBinaryString(resultFile);

                reader.onload = function(e)
                {
                    var urlData = this.result;
                    document.getElementById("result").innerHTML += urlData;
                };
            }
        }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

readAsText()

开始读取指定的Blob对象或File对象中的内容. 当读取操作完成时,readyState属性的值会成为DONE,如果设置了onloadend事件处理程序,则调用之.同时,result属性中将包含一个字符串以表示所读取的文件内容.


        function showDataByText()
        {
            var resultFile = document.getElementById("fileDemo").file

以上是关于h5新特性的主要内容,如果未能解决你的问题,请参考以下文章

H5新特性之data-*

H5,C3,ES6新特性

H5C3ES6的新特性

H5新特性websocket

H5新特性总结

H5 h5的新特性