菜单

IndexedDB数据库

2019年4月4日 - JavaScript

结论

趁着应用程序的需要的升高,你会发以往客户端高效存储大批量的多少的优势。IndexedDB是可以在浏览器中向来运用且支持异步事务的文档数据库达成。固然浏览器的援救大概否保持,但在合适的意况下,集成IndexedDB的Web应用程序具有强大的客户端数据的拜会能力。

在大部气象下,全体针对IndexedDB编写的代码是先性格基于请求和异步的。官方正式有同步API,可是这种IndexedDB只适合web
worker的上下文中使用。那篇文章发表时,还向来不浏览器完毕的协同格式的IndexedDB
API。

毫无疑问要确认保障代码在任何函数域外对厂商特定的indexedDB, IDBTransaction, and
IDBKeyRange实例进行了规范化且使用了无情形式。那允许你制止浏览器错误,当在strict
mode下解析脚本时,它不会允许你对那多少个对象重新赋值。

你必须保障只传递正整数的本子号给数据库。传递到版本号的小数值会四舍5入。因而,假若你的数据库近期版本一,您准备访问1.二本子,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=”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
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 收藏
评论

存款和储蓄数据

积存数据有二种办法:add()方法put()方法

那二种艺术的分别首要反映在:当要添加数据的目标存款和储蓄空间中早已存在有相同键的数目时,使用add()方法添加数据会报错误,而put()方法则会对现有数量举办翻新,所以add()方法壹般用来开端化数据,而put()方法用于更新数据

代码如下:

// customerData 为要存储的数据
const customerData = [{ ssn: '444-44-4444', name: 'AAA', age: 35, email: '[AAA@company.com](mailto:AAA@company.com)'},{ ssn: '666-66-6666', name: 'CCC', age: 35, email: '[CCC@company.com](mailto:CCC@company.com)'},{ ssn: '777-77-7777', name: 'DDD', age: 32, email: '[DDD@home.org](mailto:DDD@home.org)'},{ ssn: '555-55-5555', name: 'BBB', age: 32, email: '[BBB@home.org](mailto:BBB@home.org)'},
];

// 创建一个事务,该事务将要对名为“customers”的对象存储空间进行 read和write 操作,并返回事务索引
let transaction = db.transaction('customers', 'readwrite'); 

// 取得索引后,使用objectStore()方法并传入存储空间的名称,就可以访问特定的存储空间,这两步是必须的
let store = transaction.objectStore('customers'); 

// 添加数据到数据库中
for (var i in customerData) {
  // 返回的req也是一个对象,可以为其添加onsuccess和onerror事件,来检测数据是否添加成功
  let req = store.put(customerData[i]);   // 往一个存储空间中添加数据

}
// 判断事务整个操作完成
transaction.oncomplete = function(event) {
  console.log(event.target);
  alert('存储数据完成');
};
}

如上就将数据存款和储蓄到数据库dbNames的customers对象存款和储蓄空间中

上边代码中涉及了
[事务],这里先记住:凡是涉及到对数据库的读写删除操作,都亟需经过
[事务] 来完成

浏览器扶助

或是在支付Web应用程序最根本的题材是:“浏览器是还是不是帮助自身想要做的?“固然浏览器对IndexedDB的支撑在继续拉长,采取率并不是大家所企望的那样普遍。图三显得了caniuse.com网址的告知,扶助IndexedDB的为6陆%多一小点。最新版本的银狐,Chrome,Opera,Safar,iOS
Safari,和Android完全补助IndexedDB,Internet
Explorer和中兴部分协助。固然那些列表的援救者是令人鼓舞的,但它从不报告全部故事。

图片 1

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

除非可怜新本子的Safari和iOS Safari
支持IndexedDB。据caniuse.com展现,那只占大致0.0一%的海内外浏览器选择。IndexedDB不是二个您觉得能够理所当然得到扶助的现代Web
API,可是你将相当慢会这么认为。

indexDB.open()艺术的原理

分成三种意况:
1. 传到的数据库不设有
当传入的数据库不存在时,该措施就会创建二个名字为name的数据库,并打开它,此时,会先触发upgradeneeded事件;调用该函数会再次回到3个IDBRequest对象,能够在该对象上添加onsuccess事件onerror事件
注意:当打开二个不存在的数据库时会触发upgradeneeded事件,那是触发该事件的壹种途径,为啥会触发该事件吧?该事件有啥样效劳?留个难题在那时,等会解答。

二. 传来的数据仓库储存在
此处分为三种情景:

错误冒泡

理所当然,有时候,请求或然不会按预想完毕。IndexedDB
API通过荒谬冒泡效果来增加帮衬跟踪和管理漏洞百出。假若八个特定的乞求碰着错误,你能够尝尝在伸手对象上处理错误,可能您能够允许错误通过调用栈冒泡向上传递。那么些冒泡个性,使得你不要求为每个请求达成特定错误处理操作,而是可以挑选只在1个更高级别上添加错误处理,它给您1个空子,保持你的错误处理代码简洁。本文中落到实处的例证,是在三个高级别处理错误,以便更细粒度操作爆发的其余错误冒泡到通用的错误处理逻辑。

连日数据库

要利用它必须先开辟,通过 indexDB.open(name, version)措施打开一个数据库

前端的数据库:IndexedDB入门

2014/12/27 · 未分类 · IndexedDB

本文由 伯乐在线
cucr
翻译,黄利民
校稿。未经许可,禁止转发!
英文出处:www.codemag.com。欢迎插足翻译组

应用程序须要多少。对当先54%Web应用程序来说,数据在劳动器端组织和管制,客户端通过网络请求获取。随着浏览器变得尤为有力量,因而可挑选在浏览器存储和决定应用程序数据。

正文向您介绍名称为IndexedDB的浏览器端文书档案数据库。使用lndexedDB,你能够由此惯于在服务器端数据库大致等同的诀要开创、读取、更新和删除多量的笔录。请使用本文中可工作的代码版本去体会,完整的源代码能够透过GitHub库找到。

读到本课程的末段时,你将熟习IndexedDB的基本概念以及如何兑现二个运用IndexedDB执行总体的CRUD操作的模块化JavaScript应用程序。让大家多少亲近IndexedDB并起先吧。

什么是IndexedDB

貌似的话,有三种分化种类的数据库:关系型和文书档案型(也称之为NoSQL或对象)。关周全据库如SQL
Server,MySQL,Oracle的数码存款和储蓄在表中。文档数据库如MongoDB,CouchDB,Redis将数据集作为个体对象存款和储蓄。IndexedDB是三个文书档案数据库,它在完全内放置浏览器中的1个沙盒环境中(强制根据(浏览器)同源策略)。图壹来得了IndexedDB的数据,呈现了数据库的构造

图片 2

图一:开发者工具查看三个object
store

全数的IndexedDB API请参考完整文档

upgradeneeded事件

触发该事件的准绳:当打开的数据库不存在,只怕传播的数据库版本version高于当前版本,则会触发该事件

upgradeneeded事件的服从:当打开了三个数据库之后,须要开拓三个名叫:目标存款和储蓄空间
的东西(能够知道为数据就是存放在那一个空间里面,三个数据库能够成立四个对象存款和储蓄空间),而
对象存储空间 只能在upgradeneeded事件的处理函数中创设

动用时,注意以下二种状态:

  1. 当我们率先次打开创设数据库时,会接触upgradeneeded事件,大家就要求在个中创设对象存储空间

  2. 当我们对数据库版本举行更新时,也会触发该事件,那时可以在此创制新的靶子存款和储蓄空间,原来的靶子存款和储蓄空间依旧存在

注意:假若急需对指标存款和储蓄空间拓展改动,那么只好先将积存在它当中的多寡读取出来,再将其除去,然后使用新的选项去创制它,再写入原来的数目

开拓数据库并创制对象存款和储蓄空间的代码:

// 对于该API,各浏览器还未同一,所以需要对一些接口添加前缀
window.indexedDB = window.indexedDB || window.msIndexedDB || window.mozIndexedDB || window.webkitIndexedDB;
window.IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || window.msIDBTransaction || {READ_WRITE: "readwrite"};
window.IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange || window.msIDBKeyRange;
window.IDBCursor = window.IDBCursor || window.webkitIDBTransaction;

// 判断浏览器是否支持IndexedDB
if (!window.indexedDB) {
window.alert("Your browser doesn't support a stable version of IndexedDB.")
}

var request , db;
// 打开或创建 名为dbName的数据库
request = window.indexedDB.open('dbName', 2)
request.onsuccess = function (event) {
   db = event.target.result;
}

request.onerror = function (event) {
   console.log('错误代码: ' + event.target.errorCode);
}

request.onupgradeneeded = function(event) {
  db = event.target.result;  // 
  // 创建一个   对象存储空间,名为customers
  var objectStore = db.createObjectStore('customers', {keyPath: 'ssn'});
  // 对于某些数据,可以为一个对象存储空间指定多个键。比如,若要通过用户ID 和用户名 两种方式来保存用户资料,就需要通过两个键来存取记录
  // 因此可以使用createIndex,名字是有可能重复的,所以其unique 设置为 false ;第一个name是索引的名字,该名字是索引的名字,第二个name是索引的属性的名字,该名字要与对象中的属性相同
  objectStore.createIndex('name', 'name', { unique: false});

  // 创建一个email的索引,该email是独特的,所以 unique 设置为 true
  objectStore.createIndex('email', 'email', { unique: true});
}

铺设基础

本条例子从贯彻如此三个模块初阶,它承受从数据库读取数据,插入新的对象,更新现有对象,删除单个对象和提供在多个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的单对象上。其余,数据库相关的代码在1个名字为db的app子对象上。

其1模块的代码应用IIFE,通过传递window对象来确定保障模块的熨帖限制。使用use
strict确认保证那几个函数的代码函数是鲁人持竿(javascript严俊方式)严酷编写翻译规则。db对象作为与数据库交互的保有函数的首要容器。最终,window对象检查app的实例是或不是存在,倘若存在,模块使用当前实例,假诺不存在,则开创1个新对象。一旦app对象成功再次来到或创立,db对象附加到app对象。

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

行使方法

打开数据库的呼吁生命周期

IndexedDB使用事件生命周期管理数据库的打开和配置操作。图二演示了3个开辟的呼吁在早晚的环境下发生upgrade
need事件。

图片 3

图二:IndexedDB打开请求的生命周期

拥有与数据库的竞相起始于一个开拓的呼吁。试图打开数据库时,您必须传递二个被呼吁数据库的本子号的整数值。在开拓请求时,浏览器相比较你传入的用于打开请求的版本号与事实上数据库的版本号。要是所请求的版本号高于浏览器中当前的版本号(也许今后从不存在的数据库),upgrade
needed事件触发。在uprade
need事件期间,你有时机通过充足或移除stores,键和索引来操纵object stores。

若果所请求的数据库版本号和浏览器的当下版本号一致,可能升级历程一呵而就,一个开拓的数据库将再次来到给调用者。

选择游标查询数据

应用工作能够一向通过
已知的键检索单个对象。而在急需摸索七个指标时,则需求在工作内创立游标。

游标并不会提前收集结果,游标先指向结果中的第三项,在收到查找下一项的通令时,才会针对下一项

如下:

let transaction = db.transaction('customers', 'readwrite'),
let store = transaction.objectStore('customers'),
let request = store.openCursor(null) ; // 这里创建游标
request.onsuccess = function (event) {
  // event.target.result 中保存的是在存储空间中查询到的对象
  // event.target.result 中有几个属性值,可以了解到查询到的对象中的细节,
  // key: 当前访问的对象的键
  // value:当前访问的实际对象
  // primaryKey: 游标使用的键
  // direction:数值,表示游标移动的方向
  let cursor = event.target.result;
  let value, updateRequest, deleteRequest;

  // 这里必须要检查游标中是否有数据
  if (cursor) {
    if (cursor.key === '555-55-5555') {
      value = cursor.value;   // 获取到实际的访问对象
      value.name = 'hexon';   // 修改对象的name属性
      // 调用update()方法可以用指定的对象,更新对象的value
      updateRequest = cursor.update(value);     
      updateRequest.onsuccess = function() {
          // 处理成功
       }
    }
    cursor.continue() ;  // 移动到下一项,会触发下一次请求,同时成功则触发request.onsuccess
  }
}

地点例子中,能够应用cursor.delete()措施删除当前项

Implementing Database-Specific Code

对数据库的每一个操作关联着2个先决条件,即有二个打开的数据库。当数据库正在被打开时,通过检查数据库版本来判断数据库是还是不是要求别的变动。上边包车型地铁代码呈现了模块怎么样跟踪当前版本,object
store名、某成员(保存了倘使数据库打开请求实现后的数据库当前实例)。

JavaScript

version: 1, objectStoreName: ‘tasks’, instance: {},

1
2
3
version: 1,
objectStoreName: ‘tasks’,
instance: {},

在那边,数据库打开请求产生时,模块请求版本一数据库。如若数据库不设有,或然版本小于壹,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在1个警告框显示其余错误。这些函数是故意保持不难,对开发自身,当您读书运用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事件触发。

万1整个成功,打开数据库的实例能够从呼吁实例的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名字的数组。这些函数这一次被布署为只行使2个object
store,但是借使你要求在工作中操作多少个object store,你必要传递几个object
store的名字到数组中。事务函数的第二个参数是2个情势。

比方事情请求可用,您就能够通过传递须要的object
store名字来调用objectStore函数以获得object
store实例的访问权。这一个模块的此外函数使用getObjectStore来得到object
store的访问权。

下2个贯彻的函数是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事件处理程序须要安装在回调函数上,来报告调用脚本,一切进展顺遂。

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

在store访问数据时,游标遍历数据库中的每条记下,会触发onsuccess事件处理程序。当每条记下走访时,store的多少能够透过e.target.result事件参数获得。固然事实上多少从target.result的value属性中收获,首先需求在准备访问value属性前确定保证result是1个实用的值。假若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和1个回调函数。为了保全这几个完结简单,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操作成功,回调函数被执行。

事务和询问操作数据

最不难易行的创导工作的方法是:
var transaction = db.transaction(); // db就是前面的数据库对象
那种办法开创的工作,只可以读取数据库中保留的具有指标

貌似用法是:
var transaction = db.transaction('customes', 'readwrite');
代表只加载customers对象存款和储蓄空间中的数据,并且是以可读可写的方法加载

万一不传第3个参数,则象征只可访问,不可修改;

这里再次回到的transaction是业务的目录

下一场使用objectStore()主意并传播对象存款和储蓄空间的称号,就足以访问特定的存款和储蓄空间了;

如下:

let transaction = db.transaction('customers', 'readwrite'); 
let store = transaction.objectStore('customers'); 

取得了上边包车型的士store后,大家得以行使如下方法对数据进行操作:

注意:通过oncomplete事件指标,访问不到get()请求重临的别样数据,必须在响应请求的onsuccess事件处理程序中才能访问到多少

IndexedDB是不是相符自己的应用程序?

近来最重大的标题:“IndexedDB是不是相符笔者的应用程序?“像过去一律,答案是肯定的:“视情况而定。“首先当你打算在客户端保存数据时,你会考虑HTML伍地点存款和储蓄。当地存款和储蓄获得广泛浏览器的帮助,有十分不难使用的API。简单有其优势,但其劣势是力不从心支撑复杂的检索策略,存款和储蓄大批量的多寡,并提供业务协助。

IndexedDB是二个数据库。所以,当您想为客户端做出决定,思量你哪些在服务端选取一个持久化介质的数据库。你或许会问自个儿有个别难点来扶助控制客户端数据库是不是符合你的应用程序,包含:

假若您对里面包车型地铁其余难点答问了“是的”,很有非常大可能率,IndexedDB是您的应用程序的2个很好的候选。

键范围

游标也得以承受二个键,也正是因而键来设定游标查找的限制;
代码如下:

<!DOCTYPE html>
<html lang=”en”>
<head>
<meta charset=”UTF-8″>
<title>WebStorage DEMO</title>
</head>
<body>
<div class=”networkStatus”>
<button class=”clear”>清空数据</button>
<button class=”add”>添加多少</button>
<button class=”query”>查询数据</button>
<button class=”delete”>删除数据</button>
<button class=”cursor”>使用游标查询</button>
<button class=”keyRange”>使用keyrange查询</button>
<button class=”index”>使用index</button>
</div>

<script>
let network = document.querySelector(‘.networkStatus’),
addBtn = document.querySelector(‘.add’),
queryBtn = document.querySelector(‘.query’),
deleteBtn = document.querySelector(‘.delete’),
cursorBtn = document.querySelector(‘.cursor’),
clearBtn = document.querySelector(‘.clear’),
keyRange = document.querySelector(‘.keyRange’),
indexBtn = document.querySelector(‘.index’)
;

// 判断网路是还是不是在线
// if (navigator.onLine) {
// network.innerText = “网络在线”;
// } else {
// network.innerText = “互连网掉线”;
// }

// // 监察和控制互联网状态的轩然大波:online 和 offline, 那五个事件在window对象上
// window.addEventListener(‘online’, () => {
// network.innerText = “互联网在线”;
// });

// window.addEventListener(‘offline’, () => {
// network.innerText = “网络掉线”;
// });

//——–cookie的使用—————
let CookieUtil = {
get: (name) => {
let cookieName = encodeURIComponent(name) + “=”,
cookieStart = document.cookie.indexOf(cookieName),
cookieValue = null;

  if (cookieStart > -1) {
    let cookieEnd = document.cookie.indexOf(';', cookieStart);
    if (cookieEnd === -1) {
      cookieEnd = document.cookie.length;
    }
    cookieValue = decodeURIComponent(document.cookie.substring(cookieStart + cookieName.length, cookieEnd));
  }

  return cookieValue;
},
set: function (name, value, expires, path, domain, secure) {
  let cookieText = encodeURIComponent(name) + '=' +
                   encodeURIComponent(value);

  if (expires instanceof Date) {
    cookieText += '; expires=' + expires.toGMTString();
  }

  if (path) {
    cookieText += '; path=' + path;
  }

  if (domain) {
    cookieText += '; domain=' + domain;
  }

  if (secure) {
    cookieText += '; secure';
  }

  document.cookie = cookieText;
},

// 删除cookie, 并没有直接的删除cookie的方法,这里通过重新设置cookie名称,来对cookie进行替换
// 同时 将过期时间expires设置为过去的时间,
unset: function(name, path, domain, secure) {
  this.set(name, '', new Date(0), path, domain, secure);
}

}

CookieUtil.set(‘name’, ‘hexon’);
CookieUtil.set(‘book’, ‘Profession Javascript’);

// 读取cookie的值
// console.log(CookieUtil.get(‘name’));
// console.log(CookieUtil.get(‘book’));

// 删除cookie
CookieUtil.unset(‘name’);
CookieUtil.unset(‘book’);

// 设置cookie, 包蕴它的门路、域、失效日期
CookieUtil.set(‘name’, ‘Hexon’, ‘books/projs/’,
www.wrox.com’, new
Date(‘January 1, 2017’));

// 删除刚刚安装的cookie
CookieUtil.unset(‘name’, ‘books/projs/’,
www.www.wrox.com’);

// 设置安全的cookie
CookieUtil.unset(‘name’, ‘hexon’, null, null, null, null, true)

// — IndexedDB 数据库的使用
var request = window.indexedDB.open(‘dbName’, 2)
var db;
const dbName = ‘the_name’;
// 创立三个数码
const customerData = [
{ ssn: ‘444-44-4444’, name: ‘AAA’, age: 35, email:
AAA@company.com‘},
{ ssn: ‘666-66-6666’, name: ‘CCC’, age: 35, email:
CCC@company.com‘},
{ ssn: ‘777-77-7777’, name: ‘DDD’, age: 32, email:
DDD@home.org‘},
{ ssn: ‘555-55-5555’, name: ‘BBB’, age: 32, email:
BBB@home.org‘},

];

window.indexedDB = window.indexedDB || window.msIndexedDB ||
window.mozIndexedDB || window.webkitIndexedDB;
window.IDBTransaction = window.IDBTransaction ||
window.webkitIDBTransaction || window.msIDBTransaction || {READ_WRITE:
“readwrite”};
window.IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange ||
window.msIDBKeyRange;
window.IDBCursor = window.IDBCursor || window.webkitIDBTransaction;

if (!window.indexedDB) {
window.alert(“Your browser doesn’t support a stable version of
IndexedDB.”)
}

// 3是手无寸铁的数据库版本,若是名称为MyTestDatabase的数据库不存在,就会创建该数据库,然后
onupgradeneeded 事件会被触发;
// 借使数据仓库储存在,可是对版本升级了,也会触发onupgradeneeded事件,
// 注意:版本号是一个 unsigned long long
类型的值,因而不要使用float,不然会将其转移为其最接近的整数

// 生成处理程序
request.onerror = function (event) {
// do Something
alert(‘Database error: ‘ + event.target.errorCode);
};

request.onsuccess = function (event) {
// do Something
console.log(‘成立数据库成功’);
db = event.target.result; // 创设成功后,e.target.result
中蕴藏的是IDBDatabase对象的实例
}

// 当成立三个新的数额库 大概 更新已存在数据库的本子,
onupgradeneeded事件将会被触发,新的指标存款和储蓄在event.target.result中。
//
在该处理程序中,数据库已经具备先前版本的对象存款和储蓄,由此不要再度创建那个指标存款和储蓄,只需求成立任何大家要求的靶子存款和储蓄,大概
//
从此前版本中剔除不在需求的目的存款和储蓄。假若急需转移当前指标存储,则必须先删除旧的对象存款和储蓄,然后在利用新的选项创造。
// 删除旧的指标存款和储蓄,在其上的新闻都会被删去;
//
注意:该事件是唯一多少个可见对数据库举行操作的地点,在该事件之中,你对目的存储实行删除、修改或移除索引
request.onupgradeneeded = function(event) {
console.log(‘onupgradeneeded’);
var db = event.target.result;

// 创建一个   对象存储空间,名为customers
var objectStore = db.createObjectStore('customers', {keyPath: 'ssn'});
// 对于某些数据,可以为一个对象存储空间指定多个键。比如,若要通过用户ID 和用户名 两种方式来保存用户资料,就需要通过两个键来存取记录
// 因此可以使用createIndex,名字是有可能重复的,所以其unique 设置为 false ;第一个name是索引的名字,该名字是索引的名字,第二个name是索引的属性的名字,该名字要与对象中的属性相同
objectStore.createIndex('name', 'name', { unique: false});

// // 创建一个email的索引,该email是独特的,所以 unique 设置为 true
objectStore.createIndex('email', 'email', { unique: true});

}

function save(data) {
///
对于数据库的靶子存储空间中数据的读取或修改数据,都要经过事物来集团全数操作
// 最简易的创办事物的措施是:var transaction = db.transaction();
let transaction = db.transaction(‘customers’, ‘readwrite’); //
创设二个政工,并定义该事务的操作为 “readwrite” ,并重临其索引
let store = transaction.objectStore(‘customers’); //
取得索引后,使用objectStore()方法并传到存款和储蓄空间的称谓,就可以访问特定的蕴藏空间

for (var i in customerData) {
  let req = store.put(customerData[i]);   // 往一个存储空间中添加数据
}

transaction.oncomplete = function(event) {
  console.log(event.target);
  alert('存储数据完成');
};

transaction.onsuccess = function(event ) {
  console.log('onsuccess 事件');
}

}

function clear() {
// body…
let transaction = db.transaction(‘customers’, ‘readwrite’);
let store = transaction.objectStore(‘customers’).clear();
store.onerror = function(event) {
console.log(‘清空数据失利’);
}
store.onsuccess = function(event) {
console.log(‘清空数据成功’);
}
}

// 使用事务 直接通过已知的键索引 单个对象 (只可以索引单个对象)
function getData() {
let transaction = db.transaction(‘customers’, ‘readwrite’); //
创造2个事物, 并定义该工作的操作为 “readonly”
let store = transaction.objectStore(‘customers’).get(’44四-4四-4444′); //
使用get() 能够获得值

store.onerror = function (event) {
  alert('did not get the object');
}

store.onsuccess = function (event) {
  var result = event.target.result;
  console.log(result);
  alert('获取数据完成! 年龄是: ' + result.age);
}

}

function deleteData() {
let transaction = db.transaction(‘customers’, ‘readwrite’);
let store = transaction.objectStore(‘customers’);
store.delete(‘444-44-4444’);
alert(‘s删除数据形成’);
}

// 在作业内创设游标查询 能够索引 四个对象(注意: 是四个目的)
// 游标不提前手提式有线电话机结果
function cursorQuery() {
let transaction = db.transaction(‘customers’, ‘readwrite’),
store = transaction.objectStore(‘customers’),
request = store.openCursor(null) ; // 那里开创游标

request.onsuccess = function (event) {

  // event.target.result 中保存的是在存储空间中查询到的对象
  // event.target.result 中有几个属性值,可以了解到查询到的对象中的细节,
  // key: 当前访问的对象的键
  // value:当前访问的实际对象
  // primaryKey: 游标使用的键
  // direction:数值,表示游标移动的方向

  let cursor = event.target.result;
  let value, updateRequest, deleteRequest;
  if (cursor) {
  //   if (cursor.key === '555-55-5555') {
  //     value = cursor.value;   // 获取到实际的访问对象
  //     value.name = 'hexon';   // 修改对象的name属性

  //     updateRequest = cursor.update(value);      // 调用update()方法可以用指定的对象,更新对象的value
  //     updateRequest.onsuccess = function() {
  //       // 处理成功
  //     }
  //     updateRequest.onerror = function() {
  //       // 处理失败
  //     }


  //     // 使用游标删除当前项
  //     // deleteRequest = cursor.delete();
  //     // deleteRequest.onsuccess = function() {
  //     //   // 删除成功处理
  //     // }
  //     // deleteRequest.onerror = function() {
  //     //   // 删除失败处理
  //     // }


  //   }
  //   console.log(event.target.result);
  // }
  console.log(cursor.value);
  cursor.continue();      // 移动到下一项,
  }
  request.onerror = function(event) {
    console.log('游标查询创建失败')
  }
}

}

// 使用keyrange查询
function keyRangeQuery() {
let transaction = db.transaction(‘customers’, ‘readwrite’)
let store = transaction.objectStore(‘customers’);
// 使用bound()方法 定义键范围
let range = IDBKeyRange.bound(‘555-55-5555’, ‘777-77-7777’, true,
false);
// 将键传入游标创造
let request = store.openCursor(range);

request.onsuccess = function(event) {
  let cursor = event.target.result;
  if (cursor) {
    console.log('游标查询到的值' + JSON.stringify(cursor.value));
    cursor.continue()     // 移动到下一项
  }

}

request.onerror = function(event) {
  console.log("使用游标 + keyrange 查询失败")
}

}

// 使用索引
function useIndex() {
let store = db.transaction(‘customers’).objectStore(‘customers’),
index = store.index(‘name’);
request = index.openCursor();
request.onsuccess = function (event) {
let cursor = event.target.result;
if (cursor) {
console.log(cursor);
cursor.continue();
}
}
}

addBtn.addEventListener(‘click’, function(e) {
save();
}, false);

deleteBtn.addEventListener(‘click’, function(e) {
deleteData();
}, false);

queryBtn.addEventListener(‘click’, function(e) {
getData();
}, false);

cursorBtn.addEventListener(‘click’, function(e) {
cursorQuery();
}, false);

clearBtn.addEventListener(‘click’, function(e) {
clear();
}, false);

keyRange.addEventListener(‘click’, function(e) {
keyRangeQuery();
}),

indexBtn.addEventListener(‘click’, function(e) {
useIndex();
})

</script>

</body>
</html>

设计指南

IndexedDB的架构很像在局地流行的服务器端NOSQL数据库落成中的设计指南类型。面向对象数据经过object
stores(对象仓库)举行持久化,全体操作基于请求同时在业务限制内实施。事件生命周期使您可见决定数据库的布署,错误通过荒谬冒泡来使用API管理。

介绍

IndexedDB正是2个数据库
其最大的性状是:
接纳对象保存数据,而不是采取表来保存数据,同时,它是异步的

实践用户界面特定代码

于今全数特定于数据库的代码被封装在app.db模块中,用户界面特定代码能够动用此模块来与数据库交互。用户界面特定代码的一体化清单(index.ui.js)能够在清单叁中取得,完整的(index.html)页面包车型客车HTML源代码可以在清单4中获得。

使用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开首工作。

关于作者:cucr

图片 4

博客园今日头条:@hop_ping
个人主页
·
作者的稿子
·
17

图片 5

另一种选用

浏览器援救地点数据库并不是从IndexedDB才发轫达成,它是在WebSQL落到实处之后的一种新点子。类似IndexedDB,WebSQL是贰个客户端数据库,但它看成一个关周详据库的兑现,使用结构化查询语言(SQL)与数据库通讯。WebSQL的历史充满了弯曲,但底线是从未主流的浏览器厂商对WebSQL继续援救。

一旦WebSQL实际上是三个放任的技术,为啥还要提它吧?有趣的是,WebSQL在浏览器里取得稳步的支撑。Chrome,
Safari, iOS Safari, and
Android 浏览器都补助。别的,并不是那一个浏览器的风靡版本才提供帮忙,许多那些新式最棒的浏览器在此之前的本子也得以支撑。有趣的是,假如你为WebSQL添加帮忙来支持IndexedDB,你突然意识,许多浏览器厂商和本子成为匡助浏览器内置数据库的某种化身。

据此,倘若你的应用程序真正须求2个客户端数据库,你想要达到的最高级别的运用只怕,当IndexedDB不可用时,只怕你的应用程序或许看起来供给采纳采纳WebSQL来支撑客户端数据架构。即便文书档案数据库和关周全据库管理数据有鲜明的反差,但只要您有正确的肤浅,就能够利用本地数据库营造二个应用程序。

依据事务

不一样于1些价值观的关全面据库的贯彻,每二个对数据库操作是在一个事务的内外文中执行的。事务限制3回影响1个或七个object
stores,你通过传播三个object store名字的数组到创制工作限制的函数来定义。

创设工作的第二个参数是工作情势。当呼吁三个事务时,必须决定是依照只读依旧读写形式请求访问。事务是能源密集型的,所以一旦你不须要更改data
store中的数据,你只要求以只读方式对object stores集合实行呼吁访问。

清单二示范了何等运用方便的格局开创3个事务,并在那片小说的 Implementing
Database-Specific Code
 部分开始展览了详细斟酌。

应用概述

在本教程中,您将学习如何创造二个应用IndexedDB存款和储蓄数据的模块化JavaScript应用程序。为了打探应用程序是何等工作的,参考图四,它描述了职分应用程序处于空白状态。从此间你能够为列表添加新职务。图5来得了录入了多少个职务到系统的镜头。图陆出示怎么删除贰个职务,图七展现了正在编写任务时的应用程序。

图片 6

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

图片 7

图伍:义务列表

图片 8

图六:删除职分

图片 9

图柒:编辑职分
近来您熟谙的应用程序的功效,下一步是发端为网址铺设基础。

依据请求

以至于那里,有二个反复出现的大旨,您也许早就注意到。对数据库的历次操作,描述为通过三个请求打开数据库,访问三个object
store,再持续。IndexedDB
API天生是根据请求的,那也是API异步个性提示。对于你在数据库执行的历次操作,你不能不首先为那几个操作创设贰个呼吁。当呼吁完结,你能够响应由请求结果发生的轩然大波和错误。

本文达成的代码,演示了什么运用请求打开数据库,创设多个政工,读取object
store的内容,写入object store,清空object store。

对象仓库

object
store是IndexedDB数据库的底子。假诺你使用过关全面据库,常常能够将object
store等价于三个数目库表。Object
stores包含3个或多少个目录,在store中遵照一对键/值操作,这提供壹种高效稳定数据的办法。

当您安顿2个object
store,你必须为store选取叁个键。键在store中可以以“in-line”或“out-of-line”的法子存在。in-line键通过在数据对象上引用path来维持它在object
store的唯一性。为了表达这点,想想贰个席卷电子邮件地址属性Person对象。您能够布署你的store使用in-line键emailAddress,它能保证store(持久化对象中的数据)的唯1性。别的,out-of-line键通过独立于数据的值识别唯1性。在那种景况下,你能够把out-of-line键比作二个平头值,它(整数值)在关周密据库中担任记录的主键。

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

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图