HTML5新特性之客户端数据库(IndexedDB)

1、简述

在HTML5本地存储——Web SQL Database提到过Web SQL Database实际上已经被废弃(由于至今Firefox和IE不支持),而HTML5的支持的本地存储实际上变成了Web Storage(Local Storage和Session Storage)与IndexedDB。Web Storage使用简单字符串键值对在本地存储数据,方便灵活,但是对于大量结构化数据存储力不从心,IndexedDB是为了能够在客户端存储大量的结构化数据,并且使用索引高效检索的API。

2、基本特性

(1).IndexedDB是对象数据库,即NoSQL(Not Only SQL),他比支持SQL查询的数据库简单多,但是,他要比Web存储API支持的键/值对存储更加强大、更高效、更健壮。

(2).IndexedDB与Web存储和文件系统API一样,IndexedDB数据库同样受同源政策的限制(即跨域问题),也就是说两个同源的Web页面相互之间可以访问对方的数据,但是非同源的页面是无法进行访问。

(3).IndexedDB的每个源都可以有任意数目的IndexedDB数据库。但是每个数据库的名字在该源下必须是唯一的,在IndexDB API中,一个数据库其实就是一个命名的对象存储区间(Object store)的集合。

(4). NoSQL的简介:

NoSQL(NoSQL = Not Only SQL ),意即"不仅仅是SQL"。

在现代的计算系统上每天网络上都会产生庞大的数据量。

这些数据有很大一部分是由关系数据库管理系统(RDMBSs)来处理。 1970年 E.F.Codd‘s提出的关系模型的论文 "A relational model of data

for large shared data banks",

这使得数据建模和应用程序编程更加简单。

通过应用实践证明,关系模型是非常适合于客户服务器编程,远远超出预期的利益,今天它是结构化数据存储在网络和商务应用的主导技术。

NoSQL 是一项全新的数据库革命性运动,早期就有人提出,发展至2009年趋势越发高涨。NoSQL的拥护者们提倡运用非关系型的数据存储,

相对于铺天盖地的关系型数据库运用,这一概念无疑是一种全新的思维的注入。

(5).关系型数据库遵循ACID规则

5-1:A (Atomicity) 原子性

原子性很容易理解,也就是说事务里的所有操作要么全部做完,要么都不做,事务成功的条件是事务里的所有操作都成功,只要有一个操作失败,整个事务就失败,需要回滚。

比如银行转账,从A账户转100元至B账户,分为两个步骤:1)从A账户取100元;2)存入100元至B账户。这两步要么一起完成,要么一起不完成,如果只完成第一步,第二步失败,钱会莫名其妙少了100元。

5-2:C (Consistency) 一致性

一致性也比较容易理解,也就是说数据库要一直处于一致的状态,事务的运行不会改变数据库原本的一致性约束。

例如现有完整性约束a+b=10,如果一个事务改变了a,那么必须得改变b,使得事务结束后依然满足a+b=10,否则事务失败。

5-3:I (Isolation) 独立性

所谓的独立性是指并发的事务之间不会互相影响,如果一个事务要访问的数据正在被另外一个事务修改,只要另外一个事务未提交,它所访问的数据就不受未提交事务的影响。

比如现有有个交易是从A账户转100元至B账户,在这个交易还未完成的情况下,如果此时B查询自己的账户,是看不到新增加的100元的。

5-4.D (Durability) 持久性

持久性是指一旦事务提交后,它所做的修改将会永久的保存在数据库上,即使出现宕机也不会丢失。

3、异步API使用:

在IndexedDB大部分操作并不是我们常用的调用方法,返回结果的模式,而是请求——响应的模式,比如打开数据库的操作:

var request=window.indexedDB.open('testDB');

这条指令并不会返回一个DB对象的句柄,我们得到的是一个IDBOpenDBRequest对象,而我们希望得到的DB对象在其result属性中:

这条指令请求的响应是一个 IDBDatabase对象,这就是IndexedDB对象:

除了result,IDBOpenDBRequest接口定义了几个重要属性:

onerror: 请求失败的回调函数句柄

onsuccess:请求成功的回调函数句柄

onupgradeneeded:请求数据库版本变化句柄

所谓异步API是指并不是这条指令执行完毕,我们就可以使用request.result来获取indexedDB对象了,就像使用ajax一样,语句执行完并不代表已经获取到了对象,

所以我们一般在其回调函数中处理。

4.创建数据库

刚才的语句已经展示了如何打开一个indexedDB数据库,调用indexedDB.open方法就可以创建或者打开一个indexedDB。看一个完整的处理:

function openDB (name) {
            var request=window.indexedDB.open(name);
            request.onerror=function(e){
                console.log('OPen Error!');
            };
            request.onsuccess=function(e){
                myDB.db=e.target.result;
            };
        }

        var myDB={
            name:'test',
            version:1,
            db:null
        };
        openDB(myDB.name);

5.version

我们注意到除了onerror和onsuccess,IDBOpenDBRequest还有一个类似回调函数句柄——onupgradeneeded。这个句柄在我们请求打开的数据库的版本号

和已经存在的数据库版本号不一致的时候调用。

indexedDB.open()方法还有第二个可选参数,数据库版本号,数据库创建的时候默认版本号为1,当我们传入的版本号和数据库当前版本号不一致的时候

onupgradeneeded就会被调用,当然我们不能试图打开比当前数据库版本低的version,否则调用的就是onerror了,修改一下刚才例子:

function openDB (name,version) {
            var version=version || 1;
            var request=window.indexedDB.open(name,version);
            request.onerror=function(e){
                console.log(e.currentTarget.error.message);
            };
            request.onsuccess=function(e){
                myDB.db=e.target.result;
            };
            request.onupgradeneeded=function(e){
                console.log('DB version changed to '+version);
            };
        }

        var myDB={
            name:'test',
            version:3,
            db:null
        };
        openDB(myDB.name,myDB.version);

由于刚才已经创建了版本为1的数据库,打开版本为3的时候,会在控制台输出:DB version changed to 3

5.关闭与删除数据库

关闭数据库可以直接调用数据库对象的close方法:

function closeDB(db){
            db.close();
        }

删除数据库使用indexedDB对象的deleteDatabase方法:

function deleteDB(name){
            indexedDB.deleteDatabase(name);
        }

简单的使用:

var myDB={
            name:'test',
            version:3,
            db:null
        };
        openDB(myDB.name,myDB.version);
        setTimeout(function(){
            closeDB(myDB.db);
            deleteDB(myDB.name);
        },500);

由于异步API愿意,不能保证能够在closeDB方法调用前获取db对象(实际上获取db对象也比执行一条语句慢得多),

所以用了setTimeout延迟了一下。当然我们注意到每个indexedDB实例都有onclose回调函数句柄,用以数据库关闭的时候处理,

有兴趣同学可以试试,原理很简单,不演示了。

6.object store

有了数据库后我们自然希望创建一个表用来存储数据,但indexedDB中没有表的概念,而是objectStore,一个数据库中可以包含多个objectStore,

objectStore是一个灵活的数据结构,可以存放多种类型数据。也就是说一个objectStore相当于一张表,里面存储的每条数据和一个键相关联。

我们可以使用每条记录中的某个指定字段作为键值(keyPath),也可以使用自动生成的递增数字作为键值(keyGenerator),也可以不指定。

选择键的类型不同,objectStore可以存储的数据结构也有差异.

键类型 存储类型
不使用 任意值,但是没添加一条数据的时候需要指定键参数
keyPath Javascript对象,对象必须有一属性作为键值
keyGenerator 任意值
都使用 Javascript对象,如果对象中有keyPath指定的属性则不生成新的键值,如果没有自动生成递增键值,填充keyPath指定属性

7.事务:

在对新数据库做任何事情之前,需要开始一个事务。事务中需要指定该事务跨越哪些object store。

事务具有三种模式

1.只读:read,不能修改数据库数据,可以并发执行

2.读写:readwrite,可以进行读写操作

3.版本变更:verionchange

var transaction=db.transaction(['students','taecher']);  //打开一个事务,使用students 和teacher object store
var objectStore=transaction.objectStore('students'); //获取students object store

8.给object store添加数据

调用数据库实例的createObjectStore方法可以创建object store,方法有两个参数:store name和键类型。调用store的add方法添加数据。

有了上面知识,我们可以向object store内添加数据了.

keyPath:

因为对新数据的操作都需要在transaction中进行,而transaction又要求指定object store,所以我们只能在创建数据库的时候初始化

object store以供后面使用,这正是onupgradeneeded的一个重要作用,修改一下之前代码:

function openDB (name,version) {
            var version=version || 1;
            var request=window.indexedDB.open(name,version);
            request.onerror=function(e){
                console.log(e.currentTarget.error.message);
            };
            request.onsuccess=function(e){
                myDB.db=e.target.result;
            };
            request.onupgradeneeded=function(e){
                var db=e.target.result;
                if(!db.objectStoreNames.contains('students')){
                    db.createObjectStore('students',{keyPath:"id"});
                }
                console.log('DB version changed to '+version);
            };
        }

这样在创建数据库的时候我们就为其添加了一个名为students的object store,准备一些数据以供添加:

var students=[{
            id:1001,
            name:"Byron",
            age:24
        },{
            id:1002,
            name:"Frank",
            age:30
        },{
            id:1003,
            name:"Aaron",
            age:26
        }];

function addData(db,storeName){
            var transaction=db.transaction(storeName,'readwrite');
            var store=transaction.objectStore(storeName); 

            for(var i=0;i<students.length;i++){
                store.add(students[i]);
            }
        }

openDB(myDB.name,myDB.version);
        setTimeout(function(){
            addData(myDB.db,'students');
        },1000);

这样我们就在students object store里添加了三条记录,以id为键,在chrome控制台看看效果:

9.查找数据

可以调用object store的get方法通过键获取数据,以使用keyPath做键为例:

function getDataByKey(db,storeName,value){
            var transaction=db.transaction(storeName,'readwrite');
            var store=transaction.objectStore(storeName);
            var request=store.get(value);
            request.onsuccess=function(e){
                var student=e.target.result;
                console.log(student.name);
            };
}

10.更新数据

可以调用object store的put方法更新数据,会自动替换键值相同的记录,达到更新目的,没有相同的则添加,以使用keyPath做键为例

function updateDataByKey(db,storeName,value){
            var transaction=db.transaction(storeName,'readwrite');
            var store=transaction.objectStore(storeName);
            var request=store.get(value);
            request.onsuccess=function(e){
                var student=e.target.result;
                student.age=35;
                store.put(student);
            };
}

11.删除数据及object store

调用object store的delete方法根据键值删除记录

function deleteDataByKey(db,storeName,value){
            var transaction=db.transaction(storeName,'readwrite');
            var store=transaction.objectStore(storeName);
            store.delete(value);
        }

调用object store的clear方法可以清空object store

function clearObjectStore(db,storeName){
            var transaction=db.transaction(storeName,'readwrite');
            var store=transaction.objectStore(storeName);
            store.clear();
}

调用数据库实例的deleteObjectStore方法可以删除一个object store,这个就得在onupgradeneeded里面调用了

if(db.objectStoreNames.contains('students')){
                    db.deleteObjectStore('students');
}

最后:

这就是关于indexedDB的基本使用方式,很多同学看了会觉得很鸡肋,和我们正常自己定义个对象使用没什么区别,也就是能保存在本地罢了,这是因为我们还没有介绍indexedDB之所以称为indexed的杀器——索引,这个才是让indexedDB大显神通的东西,下篇我们就来看看这个杀器。

时间: 2024-08-25 02:38:34

HTML5新特性之客户端数据库(IndexedDB)的相关文章

HTML5 & CSS3初学者指南(3) – HTML5新特性

介绍 本文介绍了 HTML5 的一些新特性.主要包含以下几个方面: Web 存储 地理位置 拖放 服务器发送事件 Web存储 HTML5 Web 存储的设计与构想是一个更好的机制来存储客户端的网络数据.它是通过一个网络浏览器作为客户端数据库实现的,它允许网页以键值对的形式来存储数据. 它具有以下特征: 每个原始网站/域最多可存储 5MB 的数据. 你可以通过属性和方法来使用 JavaScript 操作 web 存储器中的数据实现访问. 就像 cookies,你可以选择将保持数据(维持),即使你已

HTML5新特性,老生常谈——前端面试常见问题

找工作面试的时候有公司技术人员会问html5新特性,那这里就再复习一遍 1.新的文档类型 <!DOCTYPE html> 2.脚本和链接无需type <link href="css/bootstrap.css" rel="stylesheet"> <script src="js/Angular.js"></script> 3.语义化的Header 和Footer 这里通俗说下什么叫做语义化,就是:明

HTML5新特性data_*自定义属性使用

HTML5 新特性data_*自定义属性使用HTML5规范里增加了一个自定义data属性. 这个自定义data属性的用法非常的简单,就是你可以往 HTML 标签上添加任意以 "data-"开头的属性, 这些属性页面上是不显示的,它不会影响到你的页面布局和风格,但它却是可读可写的. 使用 data-* 可以解决自定义属性混乱无管理的现状.

Html5新特性 &lt;canvas&gt;画板画直线

 下面例子为用canvas标签画多条直线 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta ht

Html5新特性 &amp;lt;canvas&amp;gt;画板画直线

 以下样例为用canvas标签画多条直线 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta ht

HTML5新特性新增功能

HTML5 现如今已经不是SGML的子集,主要是关于图像,位置,存储,多任务等功能的增加. 如:绘图canvas:用于媒介回放的video和audio元素:本地存储localStorage;语义化元素:表单控件等等新增的功能,都是HTML5新特性. 下面列举HTML5新特性详细说明: 一.新的文档类型  (New Doctype) 目前许多网页还在使用XHTML 1.0 并且要在第一行像这样声明文档类型: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1

HTML5新特性有哪些

HTML5新特性有哪些: 1.新的文档类型 2.脚本和链接无需 3.语义Header和Footer The Semantic Header and Footer 4.Hgroup 10.Autofocus 属性 Autofocus Attribute 12.Video 支持 Video Support 13.视频预载 Preload attribute in Videos element 14.显示控制条 15.正规表达式 5.标记元素 6.图形元素 8.占位符 9.必要属性

HTML5新特性小结

HTML5 新特性 新的DocType: <!DOCTYPE html> 不需要声明文档类型: 脚本和链接不需要type属性,如 lingk, script; 语义化标签,如:header, footer, hgroup, mark, figure, small, article, 属性及校验, 新的属性,如:placeholder, required, autofocus, pattern, autocomplete, data, contenteditable 自动校验,如: requir

HTML5新特性--svg-echarts(重点)-拖动API-WebWorker

一.html5新特性--svg--(折线/渐变特效对象/滤镜) #折线:多个坐标点组件一条折线 <polyline points="50,50 70,55 60,66 " stroke="" stroke-width=""> </polyline> #points 一组坐标点 #渐变特效对象:一种特效样式(从一种颜色慢慢过滤另一种颜色效果) #渐变特效对象:(1)创建渐变对象 <defs> (2)在指定图形应用