前端本地数据库之IndexedDB

为何出现indexedDB?

随着客户的要求越来越高,浏览器的功能不断增强,越来越多的网站开始考虑,将大量数据储存在客户端,这样可以减少从服务器获取数据,直接从本地获取数据。

然而,现有的浏览器数据储存方案,都不适合储存大量数据、或者并不提供搜索功能,不能建立自定义的索引。所以,需要一种新的解决方案,这就是 IndexedDB 诞生的背景。

何为indexedDB?

IndexedDB 是 HTML5离线存储数据的一种解决方案,是浏览器提供的本地数据库,它可以被网页脚本创建和操作。
IndexedDB 允许储存大量数据,使用索引高效搜索数据进行读写和管理操作。这些都是 LocalStorage 所不具备的。就数据库类型而言,IndexedDB 不属于关系型数据库(不支持 SQL 查询语句),更接近 NoSQL 数据库

Cookies、Localstorage、SessionStorage、IndexedDB的比较

CookiesLocalstorageSessionStorageIndexedDB
生命周期Expire设置时间永久储存(可手动清除)会话级别永久储存(可手动清除)
储存数据大小4K左右5M左右5M左右无限储存
与服务器通信cookie 的数据自动传递到服务器,服务器端也可以写在cookie到服务端不参与不参与不参与
易用性自己封装方法原生接口原生接口原生接口

indexedDB特性?

1、键值对存储:内部采用对象仓库(Object Store)存放数据,所有类型都可以直接存入(包括javascript对象),每一个数据对象对应为唯一主键(不可重复)。
2、异步:防止大量数据的读写、拖慢网页
3、支持事务:只要有一步失败,整个transaction都取消,不存在只改写一部分数据的情况,安全性更高。
4、同源限制:每一个数据库都有他对应的域名,网页只能访问自身域名对应的数据库,不能跨域访问。
5、存储空间大:IndexedDB 的储存空间比 LocalStorage 大得多,理论上没有上限。
6、支持二进制存储:除了字符串之外,储存二进制数据(ArrayBuffer 对象和 Blob 对象)

indexedDB结构?

类比sql型数据库,IndexedDB中的DB(数据库)就是sql中的DB,而Object Store(存储空间)则是数据表,Item则等于表中的一条数据对象(记录)
在这里插入图片描述

indexedDB怎么玩?

1、创建数据库

/* 调用示例
	var IDB = new OpenIndexDB({
	    "dbname":"newindexdb",//数据库名称,必填
	    "dbversion":1,//数据库版本号 不填则默认 1
	    "store":"personss"//仓库名称 不填则默认 kmgBst
	})
*/

/**
 * [OpenIndexDB 创建一个本地数据库]
 * @param {[Object]} opt [初始属性]
 */
	function OpenIndexDB(opt) {
	  const $this = this
	  // 创建indexedDB对象,兼容各种浏览器
	  const indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexedDB || window.msIndexedDB
	  if (!indexedDB) {
	    console.log('indexDB创建失败:你的浏览器不支持IndexedDB')
	    return '创建失败'
	  }
	  if (!opt.dbname) {
	    console.log('indexDB创建失败:indexDB名称不能为空')
	    return '创建失败'
	  }
	  // 初始化属性
	  $this.dbInfo = {
	    name: opt.dbname, // 数据库名称
	    version: opt.dbversion || 1, // 数据库版本号
	    store: opt.store || 'kmgBst', // 仓库名称
	    db: null, // 数据库变量
	    key: opt.key || 'key' // 关键字
	  }
	  // 创建indexDB
	  $this.opendb()
	}

2、创建indexDB

/**
 * [opendb 创建indexDB]
 */
	OpenIndexDB.prototype.opendb = function() {
	  // 定义indexDB的各项信息
	  const $this = this
	  const dbname = this.dbInfo.name
	  const dbversion = this.dbInfo.version
	  const storeName = this.dbInfo.store
	  const key = this.dbInfo.key
	  // 打开一个数据库
	  const request = indexedDB.open(dbname, dbversion)
	  // 打开失败
	  request.onerror = function(e) {
	    console.log(e.currentTarget.error.message)
	  }
	  // 打开成功!
	  request.onsuccess = function(e) {
	    $this.dbInfo.db = e.target.result
	    console.log('成功打开' + dbname)
	  }
	  // 打开成功后,如果版本有变化自动执行以下事件
	  request.onupgradeneeded = function(e) {
	    var db = e.target.result
	    if (!db.objectStoreNames.contains(storeName)) {
	      // 如果表格不存在,创建一个新的表格(keyPath,主键 ; autoIncrement,是否自增),会返回一个对象(objectStore)
	      var objectStore = db.createObjectStore(storeName, {
	        keyPath: 'id',
	        autoIncrement: true
	      })
	      // 指定可以被索引的字段,unique字段是否唯一, 指定索引可以加快搜索效率。
	      objectStore.createIndex(key, key, {
	        unique: true
	      })
	    }
	    console.log('数据库版本更改为: ' + dbversion)
	  }
	}

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

3、设置数据 setData

/**
 * [setData 设置数据]
 * @param {[Object]} opt [要储存的数据]
 */
	OpenIndexDB.prototype.setData = function(opt) {
	  // 定义indexDB的各项信息
	  const $this = this
	  const db = this.dbInfo.db
	  const storeName = this.dbInfo.store
	  const key = this.dbInfo.key
	  // 创建一个事务
	  const transaction = db.transaction(storeName, 'readwrite')
	  // 通过事务来获取store
	  const store = transaction.objectStore(storeName)
	  // 构建数据对象
	  const obj = {}
	  obj[key] = opt.key
	  obj['value'] = opt.value
	  // 往数据库添加数据
	  const addData = store.add(obj)
	  addData.onsuccess = function(e) {
	    console.log('数据添加成功')
	  }
	  addData.onerror = function(e) {
	    // 数据已存在就更新数据
	    if (e.target.error.code === 0) {
	      $this.updateData(opt.key, opt.value)
	    }
	  }
	}

4、获取数据

/**
 * [getData 获取数据]
 * @param  {[String]} keyname [通过key值名称获取数据]
 * @param  {[Function]} callback [回调函数]
 */
	OpenIndexDB.prototype.getData = function(keyname, callback) {
	  if (!keyname) { return }
	  // 定义indexDB的各项信息
	  const db = this.dbInfo.db
	  const storeName = this.dbInfo.store
	  const key = this.dbInfo.key
	  // 创建一个事务
	  const transaction = db.transaction(storeName, 'readwrite')
	  // 通过事务来获取store
	  const store = transaction.objectStore(storeName)
	  // 根据索引获取数据
	  const index = store.index(key)
	  // 根据指定的keyname获取数据
	  const request = index.get(keyname)
	  // 成功获取数据时调用
	  request.onsuccess = function(e) {
	    const data = e.target.result
	    // 调用回调函数
	    callback(data)
	  }
	  request.onerror = function(e) {
	    console.log(e)
	  }
	}

5、更新数据

/**
 * [updateData 更新数据]
 * @param  {[String]} keyname  [通过key值名称获取数据]
 * @param  {[Any]} updateData [原本的数据、替换的数据]
 * @param  {[String]} addKey  [添加的值,有该值代码在原值后面增加,否则updateData 全部替换初始值]
 */
	OpenIndexDB.prototype.updateData = function(keyname, updateData, addKey) {
	  if (!keyname) { return }
	  // 定义indexDB的各项信息
	  const db = this.dbInfo.db
	  const storeName = this.dbInfo.store
	  const key = this.dbInfo.key
	  // 创建一个事务
	  const transaction = db.transaction(storeName, 'readwrite')
	  // 通过事务来获取store
	  const store = transaction.objectStore(storeName)
	  // 根据索引获取数据
	  const index = store.index(key)
	  // 根据指定的keyname获取数据
	  const request = index.get(keyname)
	  // 成功获取数据时调用
	  request.onsuccess = function(e) {
	    const data = e.target.result
	    // 改变数据
	    if (addKey) {
	      data['value'][addKey] = updateData
	    } else {
	      data['value'] = updateData
	    }
	    // 更新数据
	    store.put(data)
	  }
	  request.onerror = function(e) {
	    console.log(e)
	  }
	}

6、删除数据库

/**
 * [deleteDatabase 删除数据库]
 * @param  {[String]} bdName  [数据库名称]
 */
	OpenIndexDB.prototype.deleteDatabase = function() {
	  const bdName = this.dbInfo.name
	  if (!bdName) { return }
	  var DBDeleteRequest = window.indexedDB.deleteDatabase(bdName)
	  DBDeleteRequest.onerror = function(event) {
	    console.log('Error')
	  }
	  DBDeleteRequest.onsuccess = function(event) {
	    console.log('success')
	  }
	}

7、调用例子

/**
 * VUE项目为例
 * 在mian.js中引入IndexDB文件
 * 创建数据库
 */
	Vue.prototype.$indexDB = new IndexDB({
	  dbname: 'Test', // 数据库名称
	  dbversion: 1, // 版本号
	  store: 'billStore' // 表名称
	})
/**
 * VUE项目为例
 * 设置数据
 */
	this.$indexDB.setData({
       key: 'dictionary',
       value: {d: 12}
     })
/**
 * VUE项目为例
 * 获取数据数据
 */
 	// 引入GETIndexDataCallback
 	import GETIndexDataCallback from '@/utils/get-indexedDB-callback'
 	import { getDictionaryList } from '@/api/common'
 	
 	const opt = {
        dbName: this.$indexDB, // 数据库名称
        key: 'Dictionary',
        api: getDictionaryList // api接口,找不到数据后,请求的接口
      }
      GETIndexDataCallback(opt, (data) => {
        console.log(data)
      })
/**
 * VUE项目为例
 * 封装获取数据,因为很多获取的时候获取可能是空的,所以需要调接口,所以综合一个方法请求
 */
 	
	function GETIndexDataCallback(opt, callback) {
	  if (!opt.dbName) {
	    return
	  }
	  // 未setData直接getData,会transaction找不到
	  try {
	    opt.dbName.getData(opt.key, function(data) {
	       // sessionStorage.getItem('setIndexedDB')是用于每次进来都更新的依据,这里可以接口自定义
	      if (data && sessionStorage.getItem('setIndexedDB')) {
	        callback && callback(data.value)
	      } else {
	        request()
	      }
	    })
	  } catch {
	    request()
	  }
	  // 调接口
	  async function request() {
	    try {
	      const res = await opt.api()
	      if (res && res.status === 0) {
	        let typeObj = res.data
	        opt.dbName.setData({
	          key: opt.key,
	          value: typeObj
	        })
	        sessionStorage.setItem('setIndexedDB', 1)
	        callback && callback(typeObj)
	      }
	    } catch {
	      console.log('res')
	    }
	  }
	}
	
	export default GETIndexDataCallback
	

8、导图
创建导图
在这里插入图片描述
调用导图
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值