由于之前的项目采用过websql作为数据存储,就是因为websql和真机的sqlite都是属于关系型数据库,可以使用sql语句进行操作,后来在实际的使用中,websql由于已被w3c抛弃很久,很多浏览器都不支持,最终决定网页版使用indexedDB进行复杂数据的存储。
以下是真机sqlite之前使用的代码
ionic sqlite 存取数据封装
indexedDB
indexedDB API
1. 启动应用成功后调用创建indexedDB对象库
indexed_db: any;//H5 indexedDB数据库对象
/**
* 创建indexed_db
*/
createIndexedDB() {
try {
let indexedDB = this.win.indexedDB || this.win.webkitIndexedDB || this.win.mozIndexedDB || this.win.msIndexedDB;
if (indexedDB) {
const request = indexedDB.open('data.db', '1');
request.onsuccess = (e: any) => {
this.indexed_db = e.target.result;
}
request.onerror = (e) => {
console.log('创建数据库失败');
}
request.onupgradeneeded = (e) => {
this.indexed_db = request.result;
//判断message是否存在,不存在则创建
if (!this.indexed_db.objectStoreNames.contains('message')) {
let messageStore = this.indexed_db.createObjectStore('message', {
keyPath: "id",//主键
autoIncrement: true//主键是否自增长
});
//指定可以被索引的字段,自由组装唯一的索引,可用于条件查询数据,unique: 字段是否唯一
messageStore.createIndex(SqlIndex.UserId, "userId", {
unique: false
});
messageStore.createIndex(SqlIndex.UserIdType, ['userId', 'msgType'], {
unique: false
});
}
}
} else {
console.log('创建数据库失败');
}
} catch (err) {
console.log('创建数据库失败');
}
}
SqlIndex值
//索引类型
export enum SqlIndex {
UserId = "userId",
UserIdType = "userId-type",
}
2. 新增数据
/**
* 操作IndexedDB
* @param storeName 对象名称
* @param data 存储的数据
*/
insertIndexedDB(storeNam: string, data: any): Promise {
return new Promise((resolve, reject) => {
//readwrite 获取读写权限
let transaction = this.indexed_db.transaction(storeNam, 'readwrite');
let store = transaction.objectStore(storeNam);
let request = store.add(data);
request.onerror = (e) => {
console.log("insert data failed");
reject(e);
}
request.onsuccess = (e) => {
resolve(e)
}
})
}
调用示例 创建message时使用了userId和msgType作为索引,索引data对象里必须含有userId和msgType字段
this.insertIndexedDB('message', { userId: 1, msgType: 1, title:'test', state: 0, content: 'content', createTime: new Date().getTime().toString()});
成功后如下图,调用操作语句必须要在insertIndexedDB函数执行成功, this.indexed_db有值后才能调用
3. 查询数据 (不能分页查询)
/**
* 获取所有数据
* @param storeNam 对象名称
* @param sqlIndex 索引
* @param indexValue 索引值
*/
getIndexedDBAll(storeNam: string, sqlIndex: string, indexValue: any): Promise {
return new Promise((resolve, reject) => {
let transaction = this.indexed_db.transaction(storeNam, 'readwrite');
let store = transaction.objectStore(storeNam);
let request = store.index(sqlIndex).getAll(indexValue);
request.onerror = (e) => {
reject(e);
}
request.onsuccess = (e) => {
resolve(e)
}
})
}
调用查询示例
this.getIndexedDBAll('message', SqlIndex.UserIdType, [1, 1]).then(data => {
if (data.target.result) {
console.log(data.target.result);
}
})
// messageStore.createIndex(SqlIndex.UserIdType, ['userId', 'msgType'], {
// unique: false
//});
创建对象库的时候曾经调用以上代码创建索引,索引查询传入的数组[1,1],第一个值表示userId =1,第二个值表示msgType =1,如图
查询最后一条数据
/**
* 获取最后一条记录
* @param storeNam 对象名称
* @param sqlIndex 索引
* @param indexValue 索引值
*/
getIndexedDBPrev(storeNam: string, sqlIndex: string, indexValue: any): Promise {
return new Promise((resolve, reject) => {
let transaction = this.indexed_db.transaction(storeNam, 'readwrite');
let store = transaction.objectStore(storeNam);
let request = store.index(sqlIndex).openCursor(indexValue, 'prev');// 对应的值有 "next" | "nextunique" | "prev" | "prevunique";
request.onerror = (e) => {
reject(e);
}
request.onsuccess = (e) => {
resolve(e)
}
})
}
根据条件索引获取数量
/**
* 获取条数
* @param storeNam 对象名称
* @param sqlIndex 索引
* @param value 索引值
*/
getIndexedDBCount(storeNam: string, sqlIndex: string, indexValue: any): Promise {
return new Promise((resolve, reject) => {
let transaction = this.indexed_db.transaction(storeNam, 'readwrite');
let store = transaction.objectStore(storeNam);
let request = store.index(sqlIndex).count(indexValue);
request.onerror = (e) => {
reject(e);
}
request.onsuccess = (e) => {
resolve(e)
}
})
}
4. 修改数据,data的数据必须是从库里查询出去,带有索引的数据
/**
* 更新数据
* @param storeNam 对象名称
* @param data 更新的数据
*/
updateIndexedDB(storeNam: string, data: any): Promise {
return new Promise((resolve, reject) => {
let transaction = this.indexed_db.transaction(storeNam, 'readwrite');
let store = transaction.objectStore(storeNam);
let request = store.put(data)
request.onerror = (e) => {
reject(e);
}
request.onsuccess = (e) => {
resolve(e)
}
})
}
5. 删除数据,只删除对象库里的某一条数据
/**
* 根据key删除
* @param key
*/
deleteIndexedDB(storeNam: string, key: any) {
var transaction = this.indexed_db.transaction(storeNam, 'readwrite');
var store = transaction.objectStore(storeNam);
store.delete(key);
}
6.清空对象数据,将会删除对象库里的所有数据
/**
* 清空数据
* @param storeNam 对象名称
*/
clearIndexedDB(storeNam: string) {
var transaction = this.indexed_db.transaction(storeNam, 'readwrite');
var store = transaction.objectStore(storeNam);
store.clear();
}
7. 版本更新(索引更新)
当前版本已经发布,但后期需要追加索引时,修改版本号1为2
const request = indexedDB.open('data.db', '2');
从而重新触发onupgradeneeded事件,那么在回调函数里面追加新建的代码
request.onupgradeneeded = (e) => {
this.indexed_db = request.result;
//判断message是否存在,不存在则创建
if (!this.indexed_db.objectStoreNames.contains('message')) {
let messageStore = this.indexed_db.createObjectStore('message', {
keyPath: "id",//主键
autoIncrement: true//主键是否自增长
});
//指定可以被索引的字段,自由组装唯一的索引,可用于条件查询数据,unique: 字段是否唯一
messageStore.createIndex(SqlIndex.UserId, "userId", {
unique: false
});
messageStore.createIndex(SqlIndex.UserIdType, ['userId', 'msgType'], {
unique: false
});
}
// 新增代码
let objectStore = e.target.transaction.objectStore('message');
objectStore.createIndex('userId-type-time', ['userId', 'msgType','createTime'], {
unique: false
});
}