`
流浪鱼
  • 浏览: 1684745 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

HTML5本地存储——IndexedDB

 
阅读更多

 

 

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

异步API

 

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

 

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

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

 

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

  • onerror: 请求失败的回调函数句柄
  • onsuccess:请求成功的回调函数句柄
  • onupgradeneeded:请求数据库版本变化句柄

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

创建数据库

 

刚才的语句已经展示了如何打开一个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);

 代码中定义了一个myDB对象,在创建indexedDB request的成功毁掉函数中,把request获取的DB对象赋值给了myDB的db属性,这样就可以使用myDB.db来访问创建的indexedDB了。

 

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 

 

关闭与删除数据库

关闭数据库可以直接调用数据库对象的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回调函数句柄,用以数据库关闭的时候处理。

 

object store

有了数据库后我们自然希望创建一个表用来存储数据,但indexedDB中没有表的概念,而是objectStore,一个数据库中可以包含多个objectStore,objectStore是一个灵活的数据结构,可以存放多种类型数据。也就是说一个objectStore相当于一张表,里面存储的每条数据和一个键相关联。

我们可以使用每条记录中的某个指定字段作为键值(keyPath),也可以使用自动生成的递增数字作为键值(keyGenerator),也可以不指定。选择键的类型不同,objectStore可以存储的数据结构也有差异。

 

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

 

事务

 在对新数据库做任何事情之前,需要开始一个事务。事务中需要指定该事务跨越哪些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

 

给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为键

 

查找数据

可以调用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); 
            };
}
 

 

更新数据

可以调用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); 
            };
}
 

 

删除数据及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中有两种索引,一种是自增长的int值,一种是keyPath:自己指定索引列,我们重点来看看keyPath方式的索引使用.

创建索引

我们可以在创建object store的时候指明索引,使用object store的createIndex创建索引,方法有三个参数

  • 索引名称
  • 索引属性字段名
  • 索引属性值是否唯一

 

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')){
                    var store=db.createObjectStore('students',{keyPath: 'id'});
                    store.createIndex('nameIndex','name',{unique:true}); 
                    store.createIndex('ageIndex','age',{unique:false}); 
                }
                console.log('DB version changed to '+version);
            };
        }
 

 

利用索引获取数据

function getDataByIndex(db,storeName){
            var transaction=db.transaction(storeName);
            var store=transaction.objectStore(storeName);
            var index = store.index("nameIndex");
            index.get('Byron').onsuccess=function(e){
                var student=e.target.result;
                console.log(student.id);
            }
        }

 这样我们可以利用索引快速获取数据,name的索引是唯一的没问题,但是对于age索引只会取到第一个匹配值,要想得到所有age符合条件的值就需要使用游标了

游标

在indexedDB中使用索引和游标是分不开的,对数据库熟悉的同学很好理解游标是什么东东,有了数据库object store的游标,我们就可以利用游标遍历object store了。

使用object store的openCursor()方法打开游标

function fetchStoreByCursor(db,storeName){
            var transaction=db.transaction(storeName);
            var store=transaction.objectStore(storeName);
            var request=store.openCursor();
            request.onsuccess=function(e){
                var cursor=e.target.result;
                if(cursor){
                    console.log(cursor.key);
                    var currentStudent=cursor.value;
                    console.log(currentStudent.name);
                    cursor.continue();
                }
            };
        }

 curson.contine()会使游标下移,知道没有数据返回undefined

index与游标结合

要想获取age为26的student,可以结合游标使用索引

function getMultipleData(db,storeName){
            var transaction=db.transaction(storeName);
            var store=transaction.objectStore(storeName);
            var index = store.index("ageIndex");
            var request=index.openCursor(IDBKeyRange.only(26))
            request.onsuccess=function(e){
                var cursor=e.target.result;
                if(cursor){
                    var student=cursor.value;
                    console.log(student.id);
                    cursor.continue();
                }
            }
        }

 这样我们可是使用索引打开一个游标,参数下面会讲到,在成功的句柄内获得游标便利age为26的student,也可以通过index.openKeyCursor()方法只获取每个对象的key值。

指定游标范围

index.openCursor()/index.openKeyCursor()方法在不传递参数的时候会获取object store所有记录,像上面例子一样我们可以对搜索进行筛选
可以使用key range 限制游标中值的范围,把它作为第一个参数传给 openCursor() 或是 openKeyCursor()
IDBKeyRange.only(value):只获取指定数据
IDBKeyRange.lowerBound(value,isOpen):获取最小是value的数据,第二个参数用来指示是否排除value值本身,也就是数学中的是否是开区间
IDBKeyRange.upperBound(value,isOpen):和上面类似,用于获取最大值是value的数据
IDBKeyRange.bound(value1,value2,isOpen1,isOpen2):不用解释了吧

获取名字首字母在B-E的student

function getMultipleData(db,storeName){
            var transaction=db.transaction(storeName);
            var store=transaction.objectStore(storeName);
            var index = store.index("nameIndex");
            var request=index.openCursor(IDBKeyRange.bound('B','F',false,
true
));
            request.onsuccess=function(e){
                var cursor=e.target.result;
                if(cursor){
                    var student=cursor.value;
                    console.log(student.name);
                    cursor.continue();
                }
            }
        }

 原文地址:http://www.cnblogs.com/dolphinX/p/3416889.html

 https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API/Using_IndexedDB

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

分享到:
评论

相关推荐

    HTML5本地存储——Web SQL Database

    HTML5是现代网页开发的重要标准,它引入了许多新特性,其中本地存储技术是提升Web应用离线可用性和性能的关键部分。Web SQL Database是HTML5早期的本地存储解决方案之一,允许Web应用程序在用户的浏览器中存储大量...

    存储篇 2:本地存储——从 Cookie 到 Web Storage、IndexDB(1).md

    除了WebStorage之外,IndexedDB是另一种更为强大的本地存储技术,它为JavaScript提供了操作数据库的能力。IndexedDB是基于磁盘的数据库系统,支持大量数据的存储,并且可以存储复杂的对象。与WebStorage不同,...

    android与html5的交互——数据库操作,UI操作,以及html5的localStorage、定位功能

    开发者可以通过JavaScript API来执行CRUD(创建、读取、更新、删除)操作,实现数据的本地存储和检索。 2. **UI操作**: HTML5提供了丰富的标签和API,如Canvas、SVG、Flexbox等,用于构建复杂的用户界面。在...

    利用html5本地数据库,实现自定义背景图片。

    此外,考虑到兼容性和未来的技术趋势,HTML5还提供了另一种本地存储方式——IndexedDB,它更适合大数据量和复杂数据结构的存储。虽然本案例使用的是Web SQL,但开发者也可以考虑使用IndexedDB来替代,因为Web SQL已...

    HTML5 JS API教程 本地数据库

    在现代网页开发中,HTML5的引入为开发者提供了许多新的功能和API,其中本地存储能力是其一大亮点。传统的Web应用依赖于Cookie或者HTTP Session来存储用户数据,但这些方法都有其局限性,如存储容量小、安全性差等。...

    js本地存储兼容版本

    除了Web Storage,HTML5还引入了更高级的数据库存储方案——`indexedDB`,它允许存储大量结构化数据,并支持索引查询。对于需要存储复杂数据结构或大量数据的应用,`indexedDB`是一个很好的选择。其API相对复杂,但...

    HTML5及CSS3web前端开发技术习题答案解析.pdf

    - **数据存储和处理功能**:提供了离线应用、Web通信、本地存储等功能,支持`WebSQL`和`IndexedDB`等轻量级数据库。 - **获取地理位置信息**:通过`Geolocation API`可以直接获取用户的地理位置信息。 - **多线程...

    HTML5 爱心表白动画

    此外,HTML5还支持离线存储(Web Storage)和本地存储(IndexedDB),这使得这个表白动画即使在网络不稳定的情况下也能流畅运行。用户可以将这个动画保存在本地,随时打开欣赏,无需担心网络连接问题。 关于标签...

    html5本地存储 localStorage操作使用详解

    本文主要探讨了HTML5中的两种本地存储形式——`localStorage`和`sessionStorage`,以及它们的用途、限制和API。 1. HTML5的几种存储形式: - **本地存储(localStorage 和 sessionStorage)**:两者都是Web ...

    前端项目-IndexedDBShim.zip

    IndexedDBShim通过使用另一种已经广泛支持的本地存储技术——WebSQL,来模拟IndexedDB的功能。WebSQL是一种基于SQLite的数据库系统,曾经被Chrome和Safari支持,但后来因为维护问题而被弃用。尽管如此,WebSQL在许多...

    w3c标准html5手册

    11. **Web SQL Database和IndexedDB**:这两个离线数据库技术为Web应用提供了本地存储大量数据的能力。 12. **Web Components**:通过自定义元素、模板(template)、阴影DOM等技术,HTML5允许开发者创建可重用、可...

    html5离线存储.pdf

    3. 本地数据存储:HTML5提供了两种本地数据存储机制——DOM Storage(包括localStorage和sessionStorage)和Web SQL Database。DOM Storage提供键值对的存储方式,数据持久化,可用于保存用户设置、游戏进度等。Web ...

    html5自学资料

    5. **Web Storage**:HTML5提供了两种本地存储机制——localStorage和sessionStorage,用于替代传统的cookie,提供更大容量的数据存储。 6. **Web Workers**:这是一个后台线程机制,允许在后台执行复杂的计算或...

    HTML5高级程序设计

    再者,HTML5的离线存储机制——离线存储应用程序(AppCache)和IndexedDB,使得开发者可以构建离线工作的Web应用。AppCache用于缓存静态资源,而IndexedDB则提供了一个键值对数据库,用于存储大量数据,这对于开发...

    微信HTML5在线朋友圈游戏源码带安装部署教程-飙车追妹子游戏.zip

    5. 存储管理:使用Web Storage或 indexedDB 存储用户的游戏数据。 四、安装部署教程 1. 准备环境:确保本地安装了Node.js和Git,用于搭建服务器和版本控制。 2. 下载源码:从提供的压缩包中解压,获取游戏源代码。 ...

    Android参考源码-三国杀版连连看(使用html5的canvas特性,纯javascript开发).zip

    通过HTML5的localStorage或IndexedDB,游戏状态可以保存在本地,即使在网络不稳定或者断开的情况下,用户仍能继续之前的游戏进度。 此外,由于这个项目是针对Android平台,因此可能考虑了移动设备的特性和优化,...

    《HTML5&CSS3开发大起底》.pdf

    之所以本书取名《HTML5&CSS3开发大起底》,是因为书中除了覆盖从网站开发到运营全过程外,横向上几乎涉及了全部的知识点——基本元素、css3样式、画布、矢量图、语义元素、本地存储、多媒体处理、点对点通讯、线程、...

Global site tag (gtag.js) - Google Analytics