新浦京娱乐场官网-301net-新浦京娱乐www.301net
做最好的网站

前端的数据库:IndexedDB入门

前端的数据库:IndexedDB入门

2014/12/27 · 未分类 · IndexedDB

本文由 伯乐在线 - cucr 翻译,黄利民 校稿。未经许可,防止转发!
葡萄牙共和国语出处:www.codemag.com。迎接插足翻译组。

应用程序需求多少。对许多Web应用程序来说,数据在劳务器端组织和管理,顾客端通过互连网诉求获取。随着浏览器变得更为有技艺,因而可选取在浏览器存款和储蓄和垄断应用程序数据。

本文向你介绍名称叫IndexedDB的浏览器端文书档案数据库。使用lndexedDB,你能够透过惯于在劳动器端数据库差不离一样的点子创造、读取、更新和删除大量的记录。请使用本文中可专门的学业的代码版本去体验,完整的源代码能够经过GitHub库找到。

读到本学科的终极时,你将熟练IndexedDB的基本概念以及怎么着实现多少个应用IndexedDB试行总体的CRUD操作的模块化JavaScript应用程序。让我们有个别亲昵IndexedDB并开端吧。

什么是IndexedDB

相似的话,有三种区别类其他数据库:关系型和文书档案型(也称为NoSQL或对象)。关全面据库如SQL Server,MySQL,Oracle的数额存款和储蓄在表中。文书档案数据库如MongoDB,CouchDB,Redis将数据集作为个体对象存款和储蓄。IndexedDB是三个文档数据库,它在一同内放置浏览器中的一个沙盒遭受中(强制依据(浏览器)同源战术)。图1呈现了IndexedDB的数量,展示了数据库的布局

图片 1

图1:开采者工具查看三个object store

不论什么事的IndexedDB API请参谋完整文书档案

设计标准

IndexedDB的架构很像在有个别流行的劳务器端NOSQL数据库达成中的设计标准类型。面向对象数据经过object stores(对象仓库)进行长久化,所有操作基于须要同一时候在业务限制内实践。事件生命周期使您可见调整数据库的布署,错误通过荒谬冒泡来使用API管理。

指标酒馆

object store是IndexedDB数据库的基本功。假如你选用过关全面据库,经常能够将object store等价于贰个数额库表。Object stores包涵三个或五个目录,在store中遵照一对键/值操作,那提供一种高效牢固数据的方法。

当您布置一个object store,你必需为store选取两个键。键在store中能够以“in-line”或“out-of-line”的方式存在。in-line键通过在数量对象上援引path来维系它在object store的独一性。为了求证那或多或少,想想三个包蕴电子邮件地址属性Person对象。您能够安顿你的store使用in-line键emailAddress,它能确认保障store(悠久化对象中的数据)的独一性。别的,out-of-line键通过单独于数据的值识别独一性。在这种状态下,你能够把out-of-line键比作一个整数值,它(整数值)在关周详据库中出任记录的主键。

图1来得了职务数据保存在任务的object store,它选取in-line键。在这一个案例中,键对应于对象的ID值。

基于事务

差异于一些观念的关全面据库的贯彻,每一个对数据库操作是在贰个作业的上下文中实行的。事务限制贰次影响二个或五个object stores,你通过传播三个object store名字的数组到创制专门的学业限制的函数来定义。

始建筑工程作的第三个参数是业务格局。当呼吁八个事务时,必得调整是鲁人持竿只读仍然读写格局央求访问。事务是能源密集型的,所以一旦您无需改换data store中的数据,你只必要以只读形式对object stores会集举行呼吁采访。

清单2示范了何等选取合适的情势创制一个业务,并在这片小说的 Implementing Database-Specific Code 部分开展了详实评论。

基于乞求

以致这里,有二个每每出现的宗旨,您恐怕曾经注意到。对数据库的每一次操作,描述为通过三个央浼打开数据库,访谈多少个object store,再持续。IndexedDB API天生是依附诉求的,那也是API异步性子提醒。对于你在数据库实践的历次操作,你必得首先为这些操作创造二个呼吁。当呼吁完毕,你能够响应由诉求结果发生的平地风波和谬误。

正文完结的代码,演示了哪些采纳央浼张开数据库,创立多少个业务,读取object store的内容,写入object store,清空object store。

张开数据库的乞求生命周期

IndexedDB使用事件生命周期管理数据库的开垦和配置操作。图2示范了二个开采的央浼在早晚的情状下发出upgrade need事件。

图片 2

图2:IndexedDB展开诉求的生命周期

具有与数据库的交互开始于一个张开的央浼。试图张开数据库时,您必需传递三个被呼吁数据库的本子号的整数值。在开荒央浼时,浏览器相比你传入的用来打开央浼的版本号与事实上数据库的版本号。即使所央浼的版本号高于浏览器中当前的版本号(可能今后并未存在的数据库),upgrade needed事件触发。在uprade need事件时期,你有机会通过丰硕或移除stores,键和索引来垄断(monopoly)object stores。

要是所乞请的数据库版本号和浏览器的当前版本号同样,大概进级历程实现,贰个开采的数据库将赶回给调用者。

错误冒泡

本来,偶然候,乞请大概不会按预期完毕。IndexedDB API通过荒谬冒泡效果来增派跟踪和管理八花九裂。要是四个一定的呼吁境遇错误,你能够尝试在呼吁对象上处理错误,或许您能够允许错误通过调用栈冒泡向上传递。那些冒泡性情,使得你不需求为每一个必要完结特定错误管理操作,而是能够选择只在三个更加高端别上加多错误管理,它给您多少个空子,保持您的错误处理代码简洁。本文中贯彻的例子,是在七个高等别管理错误,以便更加细粒度操作爆发的其余错误冒泡到通用的错误管理逻辑。

浏览器支持

兴许在付出Web应用程序最入眼的难题是:“浏览器是还是不是帮忙我想要做的?“就算浏览器对IndexedDB的帮忙在延续增加,接纳率实际不是我们所企望的那样布满。图3展现了caniuse.com网址的告诉,支持IndexedDB的为66%多一丢丢。最新版本的银狐,Chrome,Opera,Safar,iOS Safari,和Android完全补助IndexedDB,Internet Explorer和金立部分支持。即使那么些列表的跟随者是激动的,但它未有告知全体有趣的事。

图片 3

图3:浏览器对IndexedDB的支撑,来自caniuse.com

除非可怜新本子的Safari和iOS Safari 帮忙IndexedDB。据caniuse.com展现,那只占大致0.01%的中外浏览器选用。IndexedDB不是一个您以为能够道理当然是那样的得到帮助的当代Web API,不过你将急迅会这么认为。

另一种选择

浏览器补助本地数据库并非从IndexedDB才起初兑现,它是在WebSQL贯彻之后的一种新章程。类似IndexedDB,WebSQL是二个客商端数据库,但它充当一个关周全据库的实现,使用结构化查询语言(SQL)与数据库通讯。WebSQL的野史充满了波折,但底线是一直不主流的浏览器厂家对WebSQL继续匡助。

借使WebSQL实际上是一个放任的手艺,为何还要提它吗?有意思的是,WebSQL在浏览器里得到稳步的支撑。Chrome, Safari, iOS Safari, and Android 浏览器都帮衬。其他,并非那一个浏览器的摩登版本才提供支撑,许多这几个最新最好的浏览器以前的版本也得以帮助。风趣的是,借使您为WebSQL加多支持来援救IndexedDB,你忽地发掘,大多浏览器商家和本子成为支撑浏览器内置数据库的某种化身。

之所以,假设您的应用程序真正要求一个顾客端数据库,你想要达到的最高等别的使用恐怕,当IndexedDB不可用时,可能你的应用程序可能看起来必要选用使用WebSQL来援救客户端数据架构。纵然文书档案数据库和关周密据库处理数占领醒指标出入,但即使你有不错的空洞,就足以行使本地数据库创设二个应用程序。

IndexedDB是或不是合乎自己的应用程序?

目前最器重的标题:“IndexedDB是否合乎小编的应用程序?“像过去同样,答案是早晚的:“视情况而定。“首先当你希图在客商端保存数据时,你会怀想HTML5本地存款和储蓄。本地存款和储蓄获得布满浏览器的帮助,有拾分容易使用的API。简单有其优势,但其劣点是爱莫能助支撑复杂的寻找计谋,存款和储蓄多量的多少,并提供业务支持。

IndexedDB是三个数据库。所以,当您想为顾客端做出决定,思考你怎么样在服务端选拔一个漫长化介质的数据库。你恐怕会问本人有些难点来援救调节顾客端数据库是还是不是顺应你的应用程序,富含:

  • 你的客商通过浏览器访问您的应用程序,(浏览器)援助IndexedDB API吗 ?
  • 您必要仓库储存大批量的数量在客商端?
  • 你需求在多少个特大型的数额集合中非常的慢牢固单个数根据地?
  • 你的架构在顾客端需求专门的学业帮衬啊?

借令你对里面包车型地铁其余难点答疑了“是的”,很有一点都不小恐怕,IndexedDB是你的应用程序的贰个很好的候选。

使用IndexedDB

当今,你早就有空子理解了部分的欧洲经济共同体概念,下一步是始于兑现基于IndexedDB的应用程序。第二个步骤必要统一IndexedDB在不一样浏览器的贯彻。您能够很轻松地加上种种商家特性的选项的自己斟酌,同一时候在window对象上把它们设置为官方对象一样的名号。上面包车型客车清单展现了window.indexedDB,window.IDBTransaction,window.IDBKeyRange的末梢结果是怎么都被更新,它们棉被服装置为对应的浏览器的一定达成。

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;

1
2
3
4
5
6
7
8
9
10
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;

现行反革命,每一个数据库相关的全局对象具备正确的本子,应用程序能够策画选择IndexedDB开头职业。

运用概述

在本教程中,您将学习如何创制贰个用到IndexedDB存款和储蓄数据的模块化JavaScript应用程序。为了了然应用程序是怎么样做事的,参照他事他说加以考察图4,它汇报了任务应用程序处于空白状态。从那边您可认为列表增加新任务。图5来得了录入了多少个任务到系统的画面。图6体现怎么删除一个任务,图7突显了正在编纂任务时的应用程序。

图片 4

图4:空白的天职应用程序

图片 5

图5:职责列表

图片 6

图6:删除任务

图片 7

图7:编辑义务
今昔你熟稔的应用程序的效率,下一步是伊始为网址铺设基础。

铺设基础

本条例子从贯彻那样二个模块起首,它担当从数据库读取数据,插入新的靶子,更新现成对象,删除单个对象和提供在多个object store删除全数指标的选项。那个例子实现的代码是通用的数码采访代码,您能够在任何object store上接纳。

其一模块是经过一个即时实践函数表明式(IIFE)完结,它采纳对象字面量来提供组织。上面包车型客车代码是模块的摘要,表明了它的主导构造。

JavaScript

(function (window) { 'use strict'; var db = { /* implementation here */ }; window.app = window.app || {}; window.app.db = db; }(window));

1
2
3
4
5
6
7
8
(function (window) {
    'use strict';
    var db = {
        /* implementation here */
    };
    window.app = window.app || {};
    window.app.db = db;
}(window));

用如此的结构,可以使那个应用程序的有着逻辑封装在叁个名称叫app的单对象上。其它,数据库相关的代码在五个名称为db的app子对象上。

其一模块的代码应用IIFE,通过传递window对象来确定保证模块的适度限制。使用use strict确保这么些函数的代码函数是根据(javascript严酷方式)严峻编写翻译法规。db对象作为与数据库交互的有着函数的关键容器。最终,window对象检查app的实例是还是不是存在,如若存在,模块使用当前实例,假诺不设有,则开创一个新对象。一旦app对象成功重返或创建,db对象附加到app对象。

正文的其余部分将代码增添到db对象内(在implementation here会评价),为应用程序提供特定于数据库的逻辑。因而,如您所见本文后边的一些中定义的函数,想想父db对象活动,但全数其余职能都以db对象的分子。完整的数据库模块列表见清单2。

Implementing Database-Specific Code

对数据库的种种操作关联着三个先决条件,即有叁个张开的数据库。当数据库正在被张开时,通过检查数据库版本来剖断数据库是还是不是供给其他变动。上面包车型客车代码展现了模块怎么样追踪当前版本,object store名、某成员(保存了假诺数据库展开央求完结后的数据库当前实例)。

JavaScript

version: 1, objectStoreName: 'tasks', instance: {},

1
2
3
version: 1,
objectStoreName: 'tasks',
instance: {},

在此地,数据库张开恳求发生时,模块要求版本1数据库。假诺数据库官样文章,可能版本小于1,upgrade needed事件在开采乞请达成前触发。这些模块被装置为只利用一个object store,所以名字直接定义在那边。最终,实例成员被创立,它用于保存一旦张开央求落成后的数据库当前实例。

接下去的操作是落到实处upgrade needed事件的事件管理程序。在此处,检查当前object store的名字来推断央求的object store名是不是存在,假诺不设有,创建object store。

JavaScript

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 }); } },

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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
            });
    }
},

在那些事件管理程序里,通过事件参数e.target.result来访谈数据库。当前的object store名称的列表在_db.objectStoreName的字符串数组上。以后,纵然object store不设有,它是透过传递object store名称和store的键的定义(自增,关联到数码的ID成员)来制造。

模块的下八个功效是用来捕获错误,错误在模块分化的央求成立时冒泡。

JavaScript

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

1
2
3
4
errorHandler: function (error) {
    window.alert('error: ' error.target.code);
    debugger;
},

在那边,errorHandler在一个警告框展现任何错误。那几个函数是故意保持简单,对开采自身,当您读书应用IndexedDB,您能够很轻松地看到任何不当(当他们发生时)。当您策动在生产境遇使用那几个模块,您须要在这些函数中落到实处部分错误管理代码来和你的应用程序的上下文打交道。

现行反革命基础完毕了,这一节的别的部分将演示怎么样促成对数据库施行一定操作。第贰个必要检查的函数是open函数。

JavaScript

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(); }; },

1
2
3
4
5
6
7
8
9
10
11
12
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();
    };
},

open函数试图展开数据库,然后施行回调函数,告知数据库成功张开药方可策动利用。通过拜访window.indexedDB调用open函数来创设张开乞求。那几个函数接受你想打开的object store的称号和你想使用的数据库版本号。

假若央求的实例可用,第一步要扩充的干活是设置错误管理程序和进级换代函数。记住,当数据库被张开时,就算脚本恳求比浏览器里更高版本的数据库(或然只要数据库一纸空文),升级函数运维。但是,即使哀告的数据库版本相配当前数据库版本同期没错误,success事件触发。

若是整个成功,展开数据库的实例能够从呼吁实例的result属性获得,那几个实例也缓存到模块的实例属性。然后,onerror事件设置到模块的errorHandler,作为今后其余必要的一无所能捕捉管理程序。最终,回调被实行来告诉调用者,数据库已经展开并且正确地配置,能够采用了。

下贰个要兑现的函数是helper函数,它回到所乞请的object store。

JavaScript

getObjectStore: function (mode) { var txn, store; mode = mode || 'readonly'; txn = db.instance.transaction( [db.objectStoreName], mode); store = txn.objectStore( db.objectStoreName); return store; },

1
2
3
4
5
6
7
8
9
getObjectStore: function (mode) {
    var txn, store;
    mode = mode || 'readonly';
    txn = db.instance.transaction(
        [db.objectStoreName], mode);
    store = txn.objectStore(
        db.objectStoreName);
    return store;
},

在这里,getObjectStore接受mode参数,允许你决定store是以只读依然读写形式必要。对于那么些函数,暗许mode是只读的。

各种针对object store的操作都以在四个东西的光景文中实践的。事务央浼接受一个object store名字的数组。那些函数此次被安顿为只使用二个object store,然而如果你须要在业务中操作多少个object store,你供给传递七个object store的名字到数组中。事务函数的第4个参数是三个方式。

若果事情需要可用,您就能够透过传递要求的object store名字来调用objectStore函数以获得object store实例的访谈权。那个模块的别的函数使用getObjectStore来获得object store的访谈权。

下七个实现的函数是save函数,施行插入或更新操作,它依据传入的数量是不是有叁个ID值。

JavaScript

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; }); },

1
2
3
4
5
6
7
8
9
10
11
12
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;
    });
},

save函数的多个参数分别是内需保留的数目对象实例和操作成功后需求进行的回调。读写方式用于将数据写入数据库,它被流传到getObjectStore来获取object store的三个可写实例。然后,检查数据对象的ID成员是还是不是留存。借使存在ID值,数据必得立异,put函数被调用,它创设长久化央求。不然,如果ID不设有,那是新数据,add必要重返。最终,不管put可能add 央求是或不是施行了,success事件管理程序要求设置在回调函数上,来告诉调用脚本,一切进展顺遂。

下一节的代码在清单1所示。getAll函数首先张开数据库和做客object store,它为store和cursor(游标)分别设置值。为数据库游标设置游标变量允许迭代object store中的数据。data变量设置为三个空数组,充作数据的容器,它回到给调用代码。

在store访谈数据时,游标遍历数据库中的每条记下,会触发onsuccess事件管理程序。当每条记下探访时,store的数码能够由此e.target.result事件参数获得。纵然事实上数目从target.result的value属性中获取,首先须要在希图访谈value属性前确定保证result是多个有效的值。假若result存在,您能够增多result的值到数据数组,然后在result对象上调用continue函数来继承迭代object store。最终,若无reuslt了,对store数据的迭代截至,同临时候数据传递到回调,回调被推行。

现行反革命模块能够从data store获得全体数据,下八个亟需贯彻的函数是担当访谈单个记录。

JavaScript

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); }; }); },

1
2
3
4
5
6
7
8
9
10
11
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);
        };
    });
},

get函数实施的率先步操作是将id参数的值调换为二个子弹头。决意于函数被调用时,字符串或整数都恐怕传递给函数。这么些完毕跳过了对假设所给的字符串不能够调换到整数该如何是好的景色的拍卖。一旦三个id值筹算好了,数据库张开了和object store能够访问了。获取访谈get哀求出现了。央求成功时,通过传播e.target.result来进行回调。它(e.target.result)是经过调用get函数到手的单条记录。

这段时间封存和采纳操作已经冒出了,该模块还亟需从object store移除数量。

JavaScript

'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; }); },

1
2
3
4
5
6
7
8
9
10
11
'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;
    });
},

delete函数的称号用单引号,因为delete是JavaScript的保留字。这能够由你来决定。您能够选择命名函数为del或任何名目,可是delete用在那些模块为了API尽大概好的发挥。

传送给delete函数的参数是指标的id和贰个回调函数。为了保持那一个完成轻易,delete函数约定id的值为整数。您可以接纳成立一个更健全的落到实处来处理id值不能够剖析成整数的荒唐例子的回调,但为了辅导原因,代码示例是明知故犯的。

一旦id值能保险调换来二个莫西干发型,数据库被张开,二个可写的object store获得,delete函数字传送入id值被调用。当呼吁成功时,将进行回调函数。

在某个处境下,您也许须要删除三个object store的享有的记录。在这种情状下,您访谈store同期排除全数内容。

JavaScript

deleteAll: function (callback) { db.open(function () { var mode, store, request; mode = 'readwrite'; store = db.getObjectStore(mode); request = store.clear(); request.onsuccess = callback; }); }

1
2
3
4
5
6
7
8
9
deleteAll: function (callback) {
    db.open(function () {
        var mode, store, request;
        mode = 'readwrite';
        store = db.getObjectStore(mode);
        request = store.clear();
        request.onsuccess = callback;
    });
}

这里deleteAll函数担任张开数据库和拜谒object store的叁个可写实例。一旦store可用,三个新的央浼通过调用clear函数来创立。一旦clear操作成功,回调函数被实施。

实践客商分界面特定代码

近来具备特定于数据库的代码被封装在app.db模块中,顾客分界面特定代码能够应用此模块来与数据库交互。顾客分界面特定代码的欧洲经济共同体清单(index.ui.js)能够在清单3中拿走,完整的(index.html)页面包车型客车HTML源代码可以在清单4中猎取。

结论

乘机应用程序的供给的滋长,你会开采在客商端高效存款和储蓄多量的数量的优势。IndexedDB是能够在浏览器中央行政机关接选拔且援助异步事务的文书档案数据库完结。就算浏览器的补助也许或不能够保持,但在稳当的气象下,集成IndexedDB的Web应用程序具有强有力的顾客端数据的拜谒技巧。

在大多数场合下,全数针对IndexedDB编写的代码是自发基于央求和异步的。官方正式有同步API,可是这种IndexedDB只符合web worker的内外文中使用。这篇小说公布时,还未曾浏览器达成的一同格式的IndexedDB API。

分明要确定保证代码在别的函数域外对商家特定的indexedDB, IDBTransaction, and IDBKeyRange实例实行了规范化且使用了从严情势。那允许你防止浏览器错误,当在strict mode下解析脚本时,它不会允许你对那么些对象重新赋值。

你必需有限扶助只传递正整数的本子号给数据库。传递到版本号的小数值会四舍五入。因而,如果你的数据库最近版本1,您筹划访问1.2本子,upgrade-needed事件不会接触,因为版本号最后评估是一律的。

立刻施行函数表明式(IIFE)不常叫做差别的名字。不常能够见见这样的代码社团办公室法,它称为self-executing anonymous functions(自施行无名函数)或self-invoked anonymous functions(自调用佚名函数)。为进一步表明那一个名称相关的意向和含义,请阅读Ben Alman的篇章Immediately Invoked Function Expression (IIFE) 。

Listing 1: Implementing the getAll function

JavaScript

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); } }; }); },

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
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);
            }
        };
 
    });
},

Listing 2: Full source for database-specific code (index.db.js)

JavaScript

// index.db.js ; 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));

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
// index.db.js
 
;
 
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));

Listing 3: Full source for user interface-specific code (index.ui.js)

JavaScript

// index.ui.js ; (function ($, Modernizr, app) { 'use strict'; $(function(){ if(!Modernizr.indexeddb){ $('#unsupported-message').show(); $('#ui-container').hide(); return; } var $deleteAllBtn = $('#delete-all-btn'), $titleText = $('#title-text'), $notesText = $('#notes-text'), $idHidden = $('#id-hidden'), $clearButton = $('#clear-button'), $saveButton = $('#save-button'), $listContainer = $('#list-container'), $noteTemplate = $('#note-template'), $emptyNote = $('#empty-note'); var addNoTasksMessage = function(){ $listContainer.append( $emptyNote.html()); }; var bindData = function (data) { $listContainer.html(''); if(data.length === 0){ addNoTasksMessage(); return; } data.forEach(function (note) { var m = $noteTemplate.html(); m = m.replace(/{ID}/g, note.id); m = m.replace(/{TITLE}/g, note.title); $listContainer.append(m); }); }; var clearUI = function(){ $titleText.val('').focus(); $notesText.val(''); $idHidden.val(''); }; // select individual item $listContainer.on('click', 'a[data-id]', function (e) { var id, current; e.preventDefault(); current = e.currentTarget; id = $(current).attr('data-id'); app.db.get(id, function (note) { $titleText.val(note.title); $notesText.val(note.text); $idHidden.val(note.id); }); return false; }); // delete item $listContainer.on('click', 'i[data-id]', function (e) { var id, current; e.preventDefault(); current = e.currentTarget; id = $(current).attr('data-id'); app.db.delete(id, function(){ app.db.getAll(bindData); clearUI(); }); return false; }); $clearButton.click(function(e){ e.preventDefault(); clearUI(); return false; }); $saveButton.click(function (e) { var title = $titleText.val(); if (title.length === 0) { return; } var note = { title: title, text: $notesText.val() }; var id = $idHidden.val(); if(id !== ''){ note.id = parseInt(id); } app.db.save(note, function(){ app.db.getAll(bindData); clearUI(); }); }); $deleteAllBtn.click(function (e) { e.preventDefault(); app.db.deleteAll(function () { $listContainer.html(''); addNoTasksMessage(); clearUI(); }); return false; }); app.db.errorHandler = function (e) { window.alert('error: ' e.target.code); debugger; }; app.db.getAll(bindData); }); }(jQuery, Modernizr, window.app));

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
// index.ui.js
 
;
 
(function ($, Modernizr, app) {
 
    'use strict';
 
    $(function(){
 
        if(!Modernizr.indexeddb){
            $('#unsupported-message').show();
            $('#ui-container').hide();
            return;
        }
 
        var
          $deleteAllBtn = $('#delete-all-btn'),
          $titleText = $('#title-text'),
          $notesText = $('#notes-text'),
          $idHidden = $('#id-hidden'),
          $clearButton = $('#clear-button'),
          $saveButton = $('#save-button'),
          $listContainer = $('#list-container'),
          $noteTemplate = $('#note-template'),
          $emptyNote = $('#empty-note');
 
        var addNoTasksMessage = function(){
            $listContainer.append(
                $emptyNote.html());
        };
 
        var bindData = function (data) {
 
            $listContainer.html('');
 
            if(data.length === 0){
                addNoTasksMessage();
                return;
            }
 
            data.forEach(function (note) {
              var m = $noteTemplate.html();
              m = m.replace(/{ID}/g, note.id);
              m = m.replace(/{TITLE}/g, note.title);
              $listContainer.append(m);
            });
        };
 
        var clearUI = function(){
            $titleText.val('').focus();
            $notesText.val('');
            $idHidden.val('');
        };
 
        // select individual item
        $listContainer.on('click', 'a[data-id]',
 
            function (e) {
 
                var id, current;
 
                e.preventDefault();
 
                current = e.currentTarget;
                id = $(current).attr('data-id');
 
                app.db.get(id, function (note) {
                    $titleText.val(note.title);
                    $notesText.val(note.text);
                    $idHidden.val(note.id);
                });
 
                return false;
            });
 
        // delete item
        $listContainer.on('click', 'i[data-id]',
 
            function (e) {
 
                var id, current;
 
                e.preventDefault();
 
                current = e.currentTarget;
                id = $(current).attr('data-id');
 
                app.db.delete(id, function(){
                    app.db.getAll(bindData);
                    clearUI();
                });
 
                return false;
        });
 
        $clearButton.click(function(e){
            e.preventDefault();
            clearUI();
            return false;
        });
 
        $saveButton.click(function (e) {
 
            var title = $titleText.val();
 
            if (title.length === 0) {
                return;
            }
 
            var note = {
                title: title,
                text: $notesText.val()
            };
 
            var id = $idHidden.val();
 
            if(id !== ''){
                note.id = parseInt(id);
            }
 
            app.db.save(note, function(){
                app.db.getAll(bindData);
                clearUI();
            });
        });
 
        $deleteAllBtn.click(function (e) {
 
            e.preventDefault();
 
            app.db.deleteAll(function () {
                $listContainer.html('');
                addNoTasksMessage();
                clearUI();
            });
 
            return false;
        });
 
        app.db.errorHandler = function (e) {
            window.alert('error: ' e.target.code);
            debugger;
        };
 
        app.db.getAll(bindData);
 
    });
 
}(jQuery, Modernizr, window.app));

Listing 3: Full HTML source (index.html)

JavaScript

<!doctype html> <html lang="en-US"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>Introduction to IndexedDB</title> <meta name="description" content="Introduction to IndexedDB"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css"> <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs /font-awesome/4.1.0/css/font-awesome.min.css" > <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs /font-awesome/4.1.0/fonts/FontAwesome.otf" > <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs /font-awesome/4.1.0/fonts/fontawesome-webfont.eot" > <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs /font-awesome/4.1.0/fonts/fontawesome-webfont.svg" > <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs /font-awesome/4.1.0/fonts/fontawesome-webfont.ttf" > <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs /font-awesome/4.1.0/fonts/fontawesome-webfont.woff" > <style> h1 { text-align: center; color:#999; } ul li { font-size: 1.35em; margin-top: 1em; margin-bottom: 1em; } ul li.small { font-style: italic; } footer { margin-top: 25px; border-top: 1px solid #eee; padding-top: 25px; } i[data-id] { cursor: pointer; color: #eee; } i[data-id]:hover { color: #c75a6d; } .push-down { margin-top: 25px; } #save-button { margin-left: 10px; } </style> <script src="//cdnjs.cloudflare.com/ajax/libs/modernizr /2.8.2/modernizr.min.js" ></script> </head> <body class="container"> <h1>Tasks</h1> <div id="unsupported-message" class="alert alert-warning" style="display:none;"> <b>Aww snap!</b> Your browser does not support indexedDB. </div> <div id="ui-container" class="row"> <div class="col-sm-3"> <a href="#" id="delete-all-btn" class="btn-xs"> <i class="fa fa-trash-o"></i> Delete All</a> <hr/> <ul id="list-container" class="list-unstyled"></ul> </div> <div class="col-sm-8 push-down"> <input type="hidden" id="id-hidden" /> <input id="title-text" type="text" class="form-control" tabindex="1" placeholder="title" autofocus /><br /> <textarea id="notes-text" class="form-control" tabindex="2" placeholder="text"></textarea> <div class="pull-right push-down"> <a href="#" id="clear-button" tabindex="4">Clear</a> <button id="save-button" tabindex="3" class="btn btn-default btn-primary"> <i class="fa fa-save"></i> Save</button> </div> </div> </div> <footer class="small text-muted text-center">by <a href="" target="_blank">Craig Shoemaker</a> <a href="" target="_blank"> <i class="fa fa-twitter"></i></a> </footer> <script id="note-template" type="text/template"> <li> <i data-id="{ID}" class="fa fa-minus-circle"></i> <a href="#" data-id="{ID}">{TITLE}</a> </li> </script> <script id="empty-note" type="text/template"> <li class="text-muted small">No tasks</li> </script> <script src="//ajax.googleapis.com/ajax/libs /jquery/1.11.1/jquery.min.js"></script> <script src="index.db.js" type="text/javascript"></script> <script src="index.ui.js" type="text/javascript"></script> </body> </html>

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
<!doctype html>
<html lang="en-US">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <title>Introduction to IndexedDB</title>
        <meta name="description"
              content="Introduction to IndexedDB">
        <meta name="viewport"
              content="width=device-width, initial-scale=1">
        <link rel="stylesheet"
              href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
        <link rel="stylesheet"
              href="//cdnjs.cloudflare.com/ajax/libs
/font-awesome/4.1.0/css/font-awesome.min.css" >
        <link rel="stylesheet"
              href="//cdnjs.cloudflare.com/ajax/libs
/font-awesome/4.1.0/fonts/FontAwesome.otf" >
        <link rel="stylesheet"
              href="//cdnjs.cloudflare.com/ajax/libs
/font-awesome/4.1.0/fonts/fontawesome-webfont.eot" >
        <link rel="stylesheet"
              href="//cdnjs.cloudflare.com/ajax/libs
/font-awesome/4.1.0/fonts/fontawesome-webfont.svg" >
        <link rel="stylesheet"
              href="//cdnjs.cloudflare.com/ajax/libs
/font-awesome/4.1.0/fonts/fontawesome-webfont.ttf" >
        <link rel="stylesheet"
              href="//cdnjs.cloudflare.com/ajax/libs
/font-awesome/4.1.0/fonts/fontawesome-webfont.woff" >
        <style>
            h1 {
                text-align: center;
                color:#999;
            }
 
            ul li {
                font-size: 1.35em;
                margin-top: 1em;
                margin-bottom: 1em;
            }
 
            ul li.small {
                font-style: italic;
            }
 
            footer {
                margin-top: 25px;
                border-top: 1px solid #eee;
                padding-top: 25px;
            }
 
            i[data-id] {
                cursor: pointer;
                color: #eee;
            }
 
            i[data-id]:hover {
                color: #c75a6d;
            }
 
            .push-down {
                margin-top: 25px;
            }
 
            #save-button {
                margin-left: 10px;
            }
        </style>
        <script src="//cdnjs.cloudflare.com/ajax/libs/modernizr
/2.8.2/modernizr.min.js" ></script>
    </head>
    <body class="container">
        <h1>Tasks</h1>
        <div id="unsupported-message"
             class="alert alert-warning"
             style="display:none;">
            <b>Aww snap!</b> Your browser does not support indexedDB.
        </div>
        <div id="ui-container" class="row">
            <div class="col-sm-3">
 
                <a href="#" id="delete-all-btn" class="btn-xs">
                    <i class="fa fa-trash-o"></i> Delete All</a>
 
                <hr/>
 
                <ul id="list-container" class="list-unstyled"></ul>
 
            </div>
            <div class="col-sm-8 push-down">
 
                <input type="hidden" id="id-hidden" />
 
                <input
                       id="title-text"
                       type="text"
                       class="form-control"
                       tabindex="1"
                       placeholder="title"
                       autofocus /><br />
 
                <textarea
                          id="notes-text"
                          class="form-control"
                          tabindex="2"
                          placeholder="text"></textarea>
 
                <div class="pull-right push-down">
 
                    <a href="#" id="clear-button" tabindex="4">Clear</a>
 
                    <button id="save-button"
                            tabindex="3"
                            class="btn btn-default btn-primary">
                                <i class="fa fa-save"></i> Save</button>
                </div>
            </div>
        </div>
        <footer class="small text-muted text-center">by
            <a href="http://craigshoemaker.net" target="_blank">Craig Shoemaker</a>
            <a href="http://twitter.com/craigshoemaker" target="_blank">
                <i class="fa fa-twitter"></i></a>
        </footer>
        <script id="note-template" type="text/template">
            <li>
                <i data-id="{ID}" class="fa fa-minus-circle"></i>
                <a href="#" data-id="{ID}">{TITLE}</a>
            </li>
        </script>
        <script id="empty-note" type="text/template">
            <li class="text-muted small">No tasks</li>
        </script>
        <script src="//ajax.googleapis.com/ajax/libs
/jquery/1.11.1/jquery.min.js"></script>
        <script src="index.db.js" type="text/javascript"></script>
        <script src="index.ui.js" type="text/javascript"></script>
    </body>
</html>

赞 1 收藏 评论

有关笔者:cucr

图片 8

搜狐今日头条:@hop_ping 个人主页 · 笔者的小说 · 17

图片 9

本文由新浦京娱乐场官网-301net-新浦京娱乐www.301net发布于301net网站建设,转载请注明出处:前端的数据库:IndexedDB入门

您可能还会对下面的文章感兴趣: