indexedDB初体验

说到前端的本地存储方案,LocalStorage,sessionStorage 和cookie 不得不说,但是这里方案或多或少都有限制,对于不同的浏览器,他们的存储量通常不超过10M,因此碰到大量的数据存储,需要一个合适的本地存储方案,这就是indexedDB诞生的背景

indexedDB的特点:

1. 事务性数据库: 事务性意味着,只有所有操作都成功的情况下,数据存储或者修改才能执行,否则回滚到修改前的状态

2.异步:indexedDB 的操作是异步的,异步操作在执行数据读写时不会锁死浏览器,用户同时可以执行其他操作

3.支持多种形式文件存储: indexedDB不仅仅可以存储字符串,也可以存储二进制,图片等文件。

4.同源限制:IndexedDB 受到同源限制,每一个数据库对应创建它的域名。网页只能访问自身域名下的数据库,而不能访问跨域的数据库。

5.储存空间大:indexedDB的存储空间不少于250MB,甚至没有上限

indexedDB的兼容性: 兼容性相关的可以看这里 https://caniuse.com/?search=IndexedDB

使用:

1 打开(建立数据库),使用indexedDB.open()方法

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

这个方法接受两个参数,第一个参数是字符串,表示数据库的名字。如果指定的数据库不存在,就会新建数据库。第二个参数是整数,表示数据库的版本。如果省略,打开已有数据库时,默认为当前版本;新建数据库时,默认为1

indexedDB.open()方法返回一个 IDBRequest 对象。这个对象通过三种事件errorsuccessupgradeneeded,处理打开数据库的操作结果。

var db;
request.onerror = function (event) {
  console.log('数据库打开报错');
};
request.onsuccess = function (event) { 
  db
= request.result; console.log('数据库打开成功');
};

request.onupgradeneeded
= function (event) {
  db
= event.target.result;
}

这里要注意,新建一个数据库 会触发  onupgradeneeded 方法,而打开则会触发 onsuccess 方法,基于不同方法需要进行不同的处理逻辑,大家使用的时候要注意

2 建表

request.onupgradeneeded = function (event) {
  db = event.target.result;
  var objectStore;
  if (!db.objectStoreNames.contains('person')) {
    objectStore = db.createObjectStore('person', { keyPath: 'id' });
  }
}

这里新建一张为person的表,主键为id

还可以自动生成主键

var objectStore = db.createObjectStore(
  'person',
  { autoIncrement: true }
);

新建对象仓库之后,还需要新增索引

request.onupgradeneeded = function(event) {
  db = event.target.result;
  var objectStore = db.createObjectStore('person', { keyPath: 'id' });
  objectStore.createIndex('name', 'name', { unique: false });
  objectStore.createIndex('email', 'email', { unique: true });
}

上面代码中,IDBObject.createIndex()的三个参数分别为索引名称、索引所在的属性、配置对象(说明该属性是否包含重复的值)。

3.插入数据

function add() {
  var request = db.transaction(['person'], 'readwrite')
    .objectStore('person')
    .add({ id: 1, name: '张三', age: 24, email: 'zhangsan@example.com' });

  request.onsuccess = function (event) {
    console.log('数据写入成功');
  };

  request.onerror = function (event) {
    console.log('数据写入失败');
  }
}

add();

4.读取数据

function read() {
   var transaction = db.transaction(['person']);
   var objectStore = transaction.objectStore('person');
   var request = objectStore.get(1);

   request.onerror = function(event) {
     console.log('事务失败');
   };

   request.onsuccess = function( event) {
      if (request.result) {
        console.log('Name: ' + request.result.name);
        console.log('Age: ' + request.result.age);
        console.log('Email: ' + request.result.email);
      } else {
        console.log('未获得数据记录');
      }
   };
}

read();

5.遍历数据

function readAll() {
  var objectStore = db.transaction('person').objectStore('person');

   objectStore.openCursor().onsuccess = function (event) {
     var cursor = event.target.result;

     if (cursor) {
       console.log('Id: ' + cursor.key);
       console.log('Name: ' + cursor.value.name);
       console.log('Age: ' + cursor.value.age);
       console.log('Email: ' + cursor.value.email);
       cursor.continue();
    } else {
      console.log('没有更多数据了!');
    }
  };
}

readAll();

6.更新数据

function update() {
  var request = db.transaction(['person'], 'readwrite')
    .objectStore('person')
    .put({ id: 1, name: '李四', age: 35, email: 'lisi@example.com' });

  request.onsuccess = function (event) {
    console.log('数据更新成功');
  };

  request.onerror = function (event) {
    console.log('数据更新失败');
  }
}

update();

7.删除数据

function remove() {
  var request = db.transaction(['person'], 'readwrite')
    .objectStore('person')
    .delete(1);

  request.onsuccess = function (event) {
    console.log('数据删除成功');
  };
}

remove();

8.使用索引

索引的意义在于,可以让你搜索任意字段,也就是说从任意字段拿到数据记录。如果不建立索引,默认只能搜索主键(即从主键取值)。

var transaction = db.transaction(['person'], 'readonly');
var store = transaction.objectStore('person');
var index = store.index('name');
var request = index.get('李四');

request.onsuccess = function (e) {
  var result = e.target.result;
  if (result) {
    // ...
  } else {
    // ...
  }
}

这里我封装了一个方法供大家使用

  1 /**
  2  * @description: indexDB 在使用的时候,直接生产库,然后查看是否有表,有表添加数据或者修改数据,没有表就进行新增
  3  * @param databaseName => 数据库名字
  4  * @param table => 数据库表名字
  5  * @param key => 存储时候的键(indexDB是根据键值进行查询)
  6  * @param data => 进行新增的数据或者说是修改的数据,具体看调用方法
  7  * @param callback => 回调函数(indexDB是异步的,所以大部分都用回调或者Promise去执行)
  8  * @return {type} 
  9  */
 10 if (!window.localStorage.getItem('version')) {
 11     window.localStorage.setItem('version', 1)
 12 }
 13 let indexDataBase = {
 14     init: (databaseName, table, flags, callback) => {
 15         let flag = flags;
 16         let verIndex = window.localStorage.getItem('version')
 17         var request = window.indexedDB.open(databaseName, verIndex);
 18         request.onerror = () => {
 19             let errdata = {
 20                 status: 'error',
 21                 mes: '打开数据库失败!'
 22             }
 23             callback(errdata)
 24         };
 25         var indexdb;
 26         request.onsuccess = (event) => {
 27             indexdb = event.target.result;
 28             if (flag == true) {
 29                 verIndex = parseInt(window.localStorage.getItem('version')) + 1
 30                 window.localStorage.setItem('version', verIndex);
 31             } else {
 32                 verIndex = parseInt(window.localStorage.getItem('version'))
 33             }
 34             if (indexdb.objectStoreNames.length > 0) {
 35                 flag = true
 36             }
 37             indexdb.isCreate = flag;
 38             flag = false;
 39             callback(indexdb)
 40         };
 41         request.onupgradeneeded = (event) => {
 42             indexdb = event.target.result;
 43             if (!indexdb.objectStoreNames.contains(table)) {
 44                 if (flag) {
 45                     indexdb.createObjectStore(table, {
 46                         keyPath: 'id'
 47                     });
 48                 }
 49             }
 50         }
 51     },
 52     insertData: (databaseName, table, key, data, callback) => {
 53         dexie.init(databaseName, table, true, (db) => {
 54             try {
 55                 var addData = [{
 56                     id: key,
 57                     value: data
 58                 }]
 59                 var transaction = db.transaction(table, 'readwrite');
 60                 var store = transaction.objectStore(table);
 61                 for (var i = 0; i < addData.length; i++) {
 62                     store.add(addData[i]);
 63                 }
 64                 let backData = {
 65                     status: 'success',
 66                     dataBase: databaseName,
 67                     table: table,
 68                     data: addData
 69                 }
 70                 callback(backData)
 71             } catch (error) {
 72                 let errdata = {
 73                     status: 'error',
 74                     mes: '数据写入失败!'
 75                 }
 76                 callback(errdata)
 77             }
 78             db.close()
 79         })
 80     },
 81     selectData: (databaseName, table, key, callback) => {
 82         dexie.init(databaseName, table, false, (db) => {
 83             if (db.isCreate == false) {
 84                 let errdata = {
 85                     status: 'error',
 86                     mes: '获取数据失败!'
 87                 }
 88                 callback(errdata)
 89                 db.close()
 90                 return
 91             } else {
 92                 var transaction = db.transaction(table, 'readwrite');
 93                 var store = transaction.objectStore(table);
 94                 var request = store.get(key);
 95                 request.onsuccess = (e) => {
 96                     try {
 97                         var resultData = e.target.result;
 98                         let backData = {
 99                             status: 'success',
100                             dataBase: databaseName,
101                             table: table,
102                             data: resultData.value
103                         }
104                         callback(backData)
105                     } catch (error) {
106                         let errdata = {
107                             status: 'error',
108                             mes: '数据读取失败!数据库中没有该数据!'
109                         }
110                         callback(errdata)
111                     }
112                 };
113                 request.onerror = () => {
114                     let errdata = {
115                         status: 'error',
116                         mes: '数据读取失败!'
117                     }
118                     callback(errdata)
119                 }
120             }
121             db.close()
122         })
123     },
124     deleteData: (databaseName, table, key, callback) => {
125         dexie.init(databaseName, table, false, (db) => {
126             if (db.isCreate == false) {
127                 let errdata = {
128                     status: 'error',
129                     mes: '删除数据失败!'
130                 }
131                 callback(errdata)
132                 db.close()
133                 return
134             } else {
135                 var transaction = db.transaction(table, 'readwrite');
136                 var store = transaction.objectStore(table);
137 
138                 var getresult = store.get(key);
139                 let pro = new Promise((resolved) => {
140                     getresult.onsuccess = (e) => {
141                         resolved(e.target.result)
142                         db.close()
143                     }
144                 })
145                 pro.then(res => {
146                     var result = store.delete(key);
147                     if (res != undefined) {
148                         result.onsuccess = () => {
149                             let errdata = {
150                                 status: 'success',
151                                 mes: '删除成功!',
152                             }
153                             callback(errdata)
154                         }
155                         result.onerror = () => {
156                             let errdata = {
157                                 status: 'error',
158                                 mes: '删除失败!'
159                             }
160                             callback(errdata)
161                         }
162                     } else {
163                         let errdata = {
164                             status: 'error',
165                             mes: '数据库中已经没有该数据!'
166                         }
167                         callback(errdata)
168                     }
169                     db.close()
170                 })
171             }
172         })
173     },
174     changeData: (databaseName, table, key, data, callback) => {
175         dexie.init(databaseName, table, true, (db) => {
176             try {
177                 var addData = {
178                     id: key,
179                     value: data
180                 }
181                 var transaction = db.transaction(table, 'readwrite');
182                 var store = transaction.objectStore(table);
183                 store.put(addData);
184                 let backData = {
185                     status: 'success',
186                     dataBase: databaseName,
187                     table: table,
188                     data: addData
189                 }
190                 callback(backData)
191             } catch (error) {
192                 let errdata = {
193                     status: 'error',
194                     mes: '更新写入失败!'
195                 }
196                 callback(errdata)
197             }
198             db.close()
199         })
200     },
201     clearTable: (databaseName, table, callback) => {
202         dexie.init(databaseName, table, true, (db) => {
203             var transaction = db.transaction(table, 'readwrite');
204             var store = transaction.objectStore(table);
205             var result = store.clear();
206             result.onsuccess =  ()=> {
207                 let successmsg = {
208                     status: "success",
209                     msg: "数据表" + table + "清空成功!",
210                 }
211                 callback(successmsg)
212             }
213             result.onerror = () => {
214                 let successmsg = {
215                     status: "success",
216                     msg: "数据表" + table + "清空失败!",
217                 }
218                 callback(successmsg)
219             }
220         })
221     },
222     dexie: () => {
223 
224     }
225 }
226 
227 export default indexDataBase

再见!

原文地址:https://www.cnblogs.com/liuxin-673855200/p/14486107.html