使用IndexedDB的原因

提到为什么要用IndexedDB就不得不提到我们经常用的缓存API localStorage和sessionStorage,这两个缓存API能满足我们开发时的绝大多数需求,简单的键值存储,但是它们有它们的限制:

存储空间限制,只有5M
只能存储字符串,存储对象类型的数据要用JSON.stringify和parse两个方法转换
存储的字段一多就很难管理,存储的字段也无法产生关联
IndexedDB的存储空间是没有限制,但是不同浏览器可能会对IndexedDB中单个库的大小进行一定的限制,IndexedDB本质上还是一个数据库,可以存储大量结构化数据(包括文件/blobs), 同时IndexedDB API通过索引的方式实现了数据的高性能搜索

打开数据库/新建数据库

indexedDB.open(dbName, version)

  • 参数1:数据库名称(如果数据库不存在,则会新建)
  • 参数2: 数据库版本(若省略,则默认为当前版本,新建数据库时,默认为1)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

let routerDBRequest = window.indexedDB.open([dataBaseName])
<!-- error 表示数据库打开失败 -->
routerDBRequest.onerror = (event) => {
console.log('打开失败')
}

<!-- success 表示数据库打开成功 -->
routerDBRequest.onsuccess = (event) => {
console.log('打开成功')
}

<!-- 如果指定的版本号,大于数据库的实际版本号,就会发生数据库升级事件upgradeneeded -->
request.onupgradeneeded = function (event) {
db = event.target.result;
}

读取数据

objectStore.get(primaryKey)

  • 参数:主键的值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

let routerDBRequest = window.indexedDB.open('dataAnalysis')
routerDBRequest.onsuccess = (event) => {
db = event.target.result
let trans = db.transaction(['allRouteData'])
let objectStores = trans.objectStore('allRouteData')
let request = objectStores.get(1)
request.onsuccess = (event) => {
if(event.target.result) {

}
const newRoute = []
newRoute.push(event.target.result)
}
}

批量读取数据

1
2
3
4
5
6
7
8
9
10
11
12
13

objectStores.openCursor().onsuccess = (event) => {
let res = event.target.result
if(res) {
let val = res.value
newRoute.push(val)
store.dispatch('dealRouter/SaveAllRouter', newRoute)
router.push({ path: newRoute[0].path })
res.continue()
} else {
console.log('完成索引')
}
}

修改数据

objectStore.put(item)

  • 参数:一列数据
1
2
3
4
5
6
7
8
9
10
11
12

let objectStores = db.transaction(['allRouteData'], 'readwrite').objectStore('allRouteData')
const newRoute = []
objectStores.put({id: 1, name: '首页', component: 'Layout', path: '/', redirect: '/dashboard', meta:'{"title":"首页"}', children: [{
name: '首页',
path: 'dashboard',
component: 'Dashboard',
id: 2,
meta:'{"title":"首页"}'
}]
})

删除数据

objectStore.del(num)

  • 参数:删除的条数
1
2
3
4
5

let objectStores = db.transaction(['allRouteData'], 'readwrite').objectStore('allRouteData').del(1)
request.onsuccess = (event) => {
console.log('数据删除成功')
}

使用索引

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

1
2

objectStore.createIndex('name', 'name', { unique: false })

完整测试案例

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

let routerDBRequest = window.indexedDB.open('dataAnalysis')
<!-- error 表示数据库打开失败 -->
routerDBRequest.onerror = (event) => {
console.log('打开失败')
console.log(event)
}
<!-- success 表示数据库打开成功 -->
routerDBRequest.onsuccess = (event) => {
console.log('打开成功')
<!-- 读取单条数据 -->
db = event.target.result
let trans = db.transaction(['allRouteData'])
let objectStores = trans.objectStore('allRouteData')
let request = objectStores.get(1) // get参数为主键的值
request.onsuccess = (event) => {
const newRoute = []
newRoute.push(event.target.result)
store.dispatch('dealRouter/SaveAllRouter', newRoute)
router.push({ path: newRoute[0].path })
}

<!-- 批量读取数据 -->
objectStores.openCursor().onsuccess = (event) => {
let res = event.target.result
if(res) {
let val = res.value
newRoute.push(val)
store.dispatch('dealRouter/SaveAllRouter', newRoute)
router.push({ path: newRoute[0].path })
res.continue()
} else {
console.log('完成索引')
}
}

<!-- 修改数据 -->
let objectStores = db.transaction(['allRouteData'], 'readwrite').objectStore('allRouteData')
const newRoute = []
objectStores.put({id: 1, name: '首页', component: 'Layout', path: '/', redirect: '/dashboard', meta:'{"title":"首页"}', children: [{
name: '首页',
path: 'dashboard',
component: 'Dashboard',
id: 2,
meta:'{"title":"首页"}'
}]})

<!-- 删除数据 -->
let objectStores = db.transaction(['allRouteData'], 'readwrite').objectStore('allRouteData').del(1)
request.onsuccess = (event) => {
console.log('数据删除成功')
}
}
}
<!-- upgradeneeded 数据库升级事件(指定版本大于数据库实际版本时触发) -->
routerDBRequest.onupgradeneeded = (event) => {
let db = event.target.result

<!-- 创建数据仓库/新建表 -->
<!-- allRouteData为表名,keyPath为主键,使用autoIncrement可以自动生成主键 -->
if(!db.objectStoreNames.contains("allRouteData")) {
let allRoute = this.db.createObjectStore("allRouteData", { keyPath: 'id'})
<!-- IDBObject.createIndex()是新建索引的方法, 三个参数分别为索引名称、索引所在的属性、配置对象(说明该属性是否包含重复的值) -->
allRoute.createIndex('id', 'id', { unique: true })
allRoute.createIndex('name', 'name', { unique: false })
allRoute.createIndex('path', 'path', { unique: false })
allRoute.createIndex('component', 'component', { unique: false })
allRoute.createIndex('hiddenInMenu', 'hiddenInMenu', { unique: false})
allRoute.createIndex('redirect', 'redirect', {unique: false})
allRoute.createIndex('meta', 'meta', { unique: false})
}

<!-- 写入数据 -->
var objectStore = transaction.objectStore("allRouteData")
let addReq = objectStore.add(${data})
addReq.onsuccess = (event)=> {
console.log('数据写入成功')
}
addReq.onerror = (event) => {
console.log('数据写入失败')
}

<!-- 利用索引检索数据 -->
let objectStores = db.transaction(['allRouteData'], 'readwrite').objectStore('allRouteData')
let index = objectStores.index("name")
index.get('首页').onsuccess = (event)=> {
console.log(event.target.result)
}

评论