indexedDB简单介绍

indexedDB

一、其它几种前端存储:

1、cookie

HTTP cookie 通常也叫作 cookie,最初用于在客户端存储会话信息。这个规范要求服务器在响应
HTTP 请求时,通过发送 Set-Cookie HTTP 头部包含会话信息。例如, 下面是包含这个头部的一个 HTTP
响应 :

HTTP/1.1 200 OK
Content-type: text/html
Set-Cookie: name=value
Other-header: other-header-value

这个 HTTP 响应会设置一个名为"name",值为"value"的 cookie。名和值在发送时都会经过 URL
编码。浏览器会存储这些会话信息,并在之后的每个请求中都会通过 HTTP 头部 cookie 再将它们发回服
务器,比如:

GET /index.jsl HTTP/1.1
Cookie: name=value
Other-header: other-header-value

这些发送回服务器的额外信息可用于唯一标识发送请求的客户端。

cookie 是与特定域绑定的。设置 cookie 后,它会与请求一起发送到创建它的域。这个限制能保证
cookie 中存储的信息只对被认可的接收者开放,不被其他域访问。因为 cookie 存储在客户端机器上,所以为保证它不会被恶意利用,浏览器会施加限制。 同时, cookie也不会占用太多磁盘空间。

cookie 在浏览器中是由以下参数构成的(这些参数在 Set-Cookie 头部中使用分号加空格隔开 ) :

  • 名称:唯一标识 cookie 的名称。 cookie 名不区分大小写,因此 myCookie 和 MyCookie 是同一
    个名称。不过,实践中最好将 cookie 名当成区分大小写来对待,因为一些服务器软件可能这样
    对待它们。 cookie 名必须经过 URL 编码。
  • :存储在 cookie 里的字符串值。这个值必须经过 URL 编码。
  • : cookie 有效的域。发送到这个域的所有请求都会包含对应的 cookie。这个值可能包含子域(如
    www.wrox.com),也可以不包含(如.wrox.com 表示对 wrox.com 的所有子域都有效)。如果不明
    确设置,则默认为设置 cookie 的域。
  • 路径:请求 URL 中包含这个路径才会把 cookie 发送到服务器。例如,可以指定 cookie 只能由
    http://www.wrox.com/books/访问,因此访问 http://www.wrox.com/下的页面就不会发送 cookie,即
    使请求的是同一个域。
  • 过期时间:表示何时删除 cookie 的时间戳(即什么时间之后就不发送到服务器了)。默认情况下,
    浏览器会话结束后会删除所有 cookie。不过,也可以设置删除 cookie 的时间。这个值是 GMT 格
    式( Wdy, DD-Mon-YYYY HH:MM:SS GMT),用于指定删除 cookie 的具体时间。这样即使关闭
    浏览器 cookie 也会保留在用户机器上。把过期时间设置为过去的时间会立即删除 cookie。
  • 安全标志:设置之后,只在使用 SSL 安全连接的情况下才会把 cookie 发送到服务器。例如,请
    https://www.wrox.com 会发送 cookie,而请求 http://www.wrox.com 则不会 ;
HTTP/1.1 200 OK
Content-type: text/html
Set-Cookie: name=value; expires=Mon, 22-Jan-07 07:10:24 GMT; domain=.wrox.com
Other-header: other-header-value

这个头部设置一个名为"name"的 cookie,这个 cookie 在 2007 年 1 月 22 日 7:10:24 过期,对
www.wrox.com 及其他 wrox.com 的子域(如 p2p.wrox.com)有效。
安全标志 secure 是 cookie 中唯一的非名/值对,只需一个 secure 就可以了。比如:
HTTP/1.1 200 OK
Content-type: text/html
Set-Cookie: name=value; domain=.wrox.com; path=/; secure
Other-header: other-header-value
这里创建的 cookie 对所有 wrox.com 的子域及该域中的所有页面有效(通过 path=/指定)。不过,
这个 cookie 只能在 SSL 连接上发送,因为设置了 secure 标志。
要知道,域、路径、过期时间和 secure 标志用于告诉浏览器什么情况下应该在请求中包含 cookie。
这些参数并不会随请求发送给服务器,实际发送的只有 cookie 的名/值对 ;

在 JavaScript 中处理 cookie 比较麻烦,因为接口过于简单,只有 BOM 的 document.cookie 属性。
根据用法不同,该属性的表现迥异。要使用该属性获取值时, document.cookie 返回包含页面中所有
有效 cookie 的字符串(根据域、路径、过期时间和安全设置),以分号分隔,如下面的例子所示:
name1=value1;name2=value2;name3=value3
所有名和值都是 URL 编码的,因此必须使用 decodeURIComponent()解码。
在设置值时,可以通过 document.cookie 属性设置新的 cookie 字符串。这个字符串在被解析后会
添加到原有 cookie 中。设置 document.cookie 不会覆盖之前存在的任何 cookie,除非设置了已有的
cookie。设置 cookie 的格式如下,与 Set-Cookie 头部的格式一样:
name=value; expires=expiration_time; path=domain_path; domain=domain_name; secure
在所有这些参数中,只有 cookie 的名称和值是必需的。下面是个简单的例子:
document.cookie = "name=Nicholas";
这行代码会创建一个名为"name"的会话 cookie,其值为"Nicholas"。这个 cookie 在每次客户端向
服务器发送请求时都会被带上,在浏览器关闭时就会被删除。虽然这样直接设置也可以,因为不需要在
名称或值中编码任何字符,但最好还是使用 encodeURIComponent()对名称和值进行编码,比如:
document.cookie = encodeURIComponent("name") + "=" +
encodeURIComponent("Nicholas");
要为创建的 cookie 指定额外的信息,只要像 Set-Cookie 头部一样直接在后面追加相同格式的字
符串即可:
document.cookie = encodeURIComponent("name") + "=" +
encodeURIComponent("Nicholas") + "; domain=.wrox.com; path=/";

因为在 JavaScript 中读写 cookie 不是很直观,所以可以通过辅助函数来简化相应的操作。与 cookie
相关的基本操作有读、写和删除。这些在 CookieUtil 对象中表示如下:

class CookieUtil {
	static 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;
	}
	static set(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;
	}
	static unset(name, path, domain, secure) {
		CookieUtil.set(name, "", new Date(0), path, domain, secure);
	}
};
// 可以像下面这样使用这些方法:
// 设置 cookie
CookieUtil.set("name", "Nicholas");
CookieUtil.set("book", "Professional JavaScript");
// 读取 cookie
alert(CookieUtil.get("name")); // "Nicholas"
alert(CookieUtil.get("book")); // "Professional JavaScript"
// 删除 cookie
CookieUtil.unset("name");
CookieUtil.unset("book");
// 设置有路径、域和过期时间的 cookie
CookieUtil.set("name", "Nicholas", "/books/projs/", "www.wrox.com",
new Date("January 1, 2010"));
// 删除刚刚设置的 cookie
CookieUtil.unset("name", "/books/projs/", "www.wrox.com");
// 设置安全 cookie
CookieUtil.set("name", "Nicholas", null, null, null, true);
// 这些方法通过处理解析和 cookie 字符串构建,简化了使用 cookie 存储数据的操作
2、Storage

Web Storage 的定义了两个对象: localStorage 和 sessionStorage。 localStorage 是永久存储机制, sessionStorage 是跨会话的存储机制。这两种浏览器存储 API 提供了在浏览器中不受页面刷新影响而存储数据的两种方式。

Storage 类型用于保存名/值对数据,直至存储空间上限(由浏览器决定)。 Storage 的实例与其他
对象一样,但增加了以下方法 :

  • clear():删除所有值;不在 Firefox 中实现。
  • getItem(name):取得给定 name 的值
  • key(index):取得给定数值位置的名称
  • removeItem(name):删除给定 name 的名/值对
  • setItem(name, value):设置给定 name 的值。

sessionStorage:

因为 sessionStorage 对象是 Storage 的实例,所以可以通过使用 setItem()方法或直接给属
性赋值给它添加数据。下面是使用这两种方式的例子:
// 使用方法存储数据
sessionStorage.setItem("name", "Nicholas");
// 使用属性存储数据
sessionStorage.book = "Professional JavaScript";

可以使用 getItem()或直接访问属性名来取得。下面是使用这两种方式的例子:

// 使用方法取得数据
let name = sessionStorage.getItem("name");
// 使用属性取得数据
let book = sessionStorage.book;

可以结合 sessionStorage 的 length 属性和 key()方法遍历所有的值:

for (let i = 0, len = sessionStorage.length; i < len; i++){
	let key = sessionStorage.key(i);
	let value = sessionStorage.getItem(key);
	alert(`${key}=`${value}`);
}  
for (let key in sessionStorage){
	let value = sessionStorage.getItem(key);
	alert(`${key}=${value}`);
}

要从 sessionStorage 中删除数据,可以使用 delete 操作符直接删除对象属性,也可以使用
removeItem()方法。下面是使用这两种方式的例子:

// 使用 delete 删除值
delete sessionStorage.name;
// 使用方法删除值
sessionStorage.removeItem("book");

sessionStorage 对象应该主要用于存储只在会话期间有效的小块数据。如果需要跨会话持久存储
数据,可以使用 globalStorage 或 localStorage

存储在 localStorage 中的数据会保留到通过 JavaScript 删除或者用户清除浏览器缓存。 localStorage 数据不受页面刷新影响,也不会因关闭窗口、标签页或重新启动浏览器而丢失。

存储事件

每当 Storage 对象发生变化时,都会在文档上触发 storage 事件。使用属性或 setItem()设置
值、使用 delete 或 removeItem()删除值,以及每次调用 clear()时都会触发这个事件。这个事件的
事件对象有如下 4 个属性。

  • domain:存储变化对应的域。

  • key:被设置或删除的键。

  • newValue:键被设置的新值,若键被删除则为 null。

  • oldValue:键变化之前的值。

    可以使用如下代码监听 storage 事件:

    window.addEventListener("storage",(event) => 
         alert('Storage changed for ${event.domain}'
    ));
    

    对于 sessionStorage 和 localStorage 上的任何更改都会触发 storage 事件,但 storage 事
    件不会区分这两者。

二、indexedDB简介

IndexedDB和传统的关系型数据不同的是,它是一个key-value型的数据库。

value可以是复杂的结构体对象,key可以是对象的某些属性值也可以是其他的对象(包括二进制对象)。你可以使用对象中的任何属性做为index,以加快查找。

IndexedDB是自带transaction的,所有的数据库操作都会绑定到特定的事务上,并且这些事务是自动提交了,IndexedDB并不支持手动提交事务。

IndexedDB API大部分都是异步的,在使用异步方法的时候,API不会立马返回要查询的数据,而是返回一个callback。

异步API的本质是向数据库发送一个操作请求,当操作完成的时候,会收到一个DOM event,通过该event,我们会知道操作是否成功,并且获得操作的结果。

IndexedDB是一种 NoSQL 数据库,和关系型数据库不同的是,IndexedDB是面向对象的,它存储的是Javascript对象。

IndexedDB还有一个很重要的特点是其同源策略,每个源都会关联到不同的数据库集合,不同源是不允许访问其他源的数据库,从而保证了IndexedDB的安全性。

三、使用原因:开发者需要在本地进行永久存储

当我们进行一些较大的SPA页面开发时,我们会需要进行一些数据的本地存储。

当数据量不大时,我们可以通过SessionStorage或者LocalStorage来进行存储,但是当数据量较大,或符合一定的规范时,我们可以使用数据库来进行数据的存储。

在浏览器提供的数据库中,共有web sql和IndexedDB两种。相较于HTML5已经废弃的web sql来说,更推荐大家使用IndexedDB。

四、indexedDB的相关操作

// 假如一开始有这样的数据需要存储
let data = [
    {
        id: 1,
        name: "lzc",
        age: 18,
        sex: "man",
        addTime: "2021-2-1"
    },
    {
        id: 2,
        name: "cb",
        age: 19,
        sex: "man",
        addTime: "2021-2-2"
    },
    {
        id: 3,
        name: "kj",
        age: 20,
        sex: "woman",
        addTime: "2021-2-3"
    },
    {
        id: 4,
        name: "juanjuan",
        age: 21,
        sex: "woman",
        addTime: "2021-2-4"
    }
]
1、创建或者打开数据库
/*
不同的浏览器对于IndexedDB有不同的实现,正常来说,我们可以使用window.indexedDB来获取到浏览器的indexedDB对象。但是对于某些浏览器来说,还没有使用标准的window.indexedDB,而是用带前缀的实现

使用IndexedDB第一步,就是创建或打开一个数据库。我们使用window.indexedDB.open(DBName)这个API来打进行操作。
*/
window.indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;

if (!window.indexedDB) {
    console.log("Your browser doesn't support a stable version of IndexedDB. Such and such feature will not be available.");
} else {
    const request = window.indexedDB.open('people');

    request.onupgradeneeded = function (event) {

    }

    request.onsuccess = function(event) {
        console.log(request === event.target) // true
    }
    request.onerror = function(event) {
        
    }
}
  • 调用此接口时,如果当前数据库不存在,则会创建一个新的数据库;
  • 当数据库建立连接时,会返回一个IDBOpenDBRequest对象。
  • 在连接建立成功时,会触发onsuccess事件,其中函数参数eventtarget属性就是request对象。
  • 而在数据库创建或者版本更新时,会触发onupgradeneeded事件。
2、更新数据库版本号

window.indexedDB.open的第二个参数即为版本号。在不指定的情况下,默认版本号为1。

const request = window.indexedDB.open('people', 2);

在需要更新数据库的schema(模式)时,需要更新版本号。此时我们指定一个高于之前版本的版本号,就会触发onupgradeneeded事件。类似的,当此数据库不存在时,也会触发此事件并且将版本更新到置顶版本。

我们需要注意的是,版本号是一个Unsigned long long数字,这意味着它可以是一个非常大的整数。但是,它不能是一个小数,否则它将会被转为最近的整数,同时有可能导致onUpgradeneeded事件不触发(bug)。

3、存储空间操作

我们使用createObjectStore来创建一个存储空间。同时,使用createIndex来创建它的索引。

var request = window.indexedDB.open('people', 1);

request.onupgradeneeded = function (event) {
 console.log(request === event.target) // true
 var db = event.target.result;
 var objectStore = db.createObjectStore('user', {keyPath: 'id', autoIncrement: true});
	// 可以循环遍历,给对象数组或者对象的每个键都生成索引(每个索引里面的数据项的排序按索引的升序来排列,索引没有顺序可言,就按原始顺序)
	if (Object.prototype.toString.call(data) === "[object Array]" && data.length) {
     for (let i in data[0]) {
         objectStore.createIndex(i, i, { unique: false })
     }
 } else if (Object.prototype.toString.call(data) === "[object object]") {
     for (let i in data) {
         objectStore.createIndex(i, i, { unique: false })
     }
 }
}

request.onerror = function (event) {
 alert("Why didn't you allow my web app to use IndexedDB?!");
};

注:只能在onupgradeneeded回调函数中创建存储空间,而不能在数据库打开后的success回调函数中创建。

通过createObjectStore能够创建一个存储空间。接受两个参数:

  1. 第一个参数,存储空间的名称,即我们上面的user
  2. 第二个参数,指定存储的keyPath值为存储对象的某个属性,这个属性能够在获取存储空间数据的时候当做key值使用。autoIncrement指定了key值是否自增(当key值为默认的从1开始到2^53的整时)。

createIndex能够给当前的存储空间设置一个索引。它接受三个参数:

  1. 第一个参数,索引的名称。
  2. 第二个参数,指定根据存储数据的哪一个属性来构建索引。
  3. 第三个属性, options对象,其中属性unique的值为true表示不允许索引值相等。
4、数据操作
1、事务transaction

IndexedDB中,我们使用事务transaction来进行数据库的操作。事务有三个模式(常量已经弃用)

  • readOnly:只读。
  • readwrite:读写。
  • versionchange:数据库版本变化。

我们创建一个事务时,需要从上面选择一种模式,如果不指定的话,则默认为只读模式

const transaction = db.transaction(['user'], 'readwrite');

事务函数transaction的第一个参数为需要关联的存储空间,第二个可选参数为事务模式。与上面类似,事务成功时也会触发onsuccess函数,失败时触发onerror函数。

2、增加数据

当存储空间objectStore初始化完成后,我们可以把数据放入存储空间中。可以使用 add()或 put()写入数据。这两个方法都接收一个参数, 即要存储的对象,并把对象保存到对象存储。这两个方法只在对象存储中已存在同名的键时有区别。这 种情况下,add()会导致错误,而 put()会简单地重写该对象

var request = window.indexedDB.open('people', 1);

request.onsuccess = function (event) {
    var db = event.target.result;

    var transaction = db.transaction(['user'], 'readwrite');

    var objectStore = transaction.objectStore('user');

    for (let item of data) {
        objectStore.add(item);
    }
}

注:add方法中的第二个参数key值是指定存储空间中的keyPath值,如果data中包含keyPath值或者此值为自增值,那么可以略去此参数。

// 1、createObjectStore第二个参数里加 { autoIncrement: true },这个时候key使用从1开始的自增数,遍历出来的数据和原始要存储的数据顺序一致;
// 2、objectStore.add(item, item.name); 指定了keyPath值,这时候遍历出来的数据顺序,可能和原始的不一样,这里是按照keyPath值字母语序来排列的;这里写不写{ autoIncrement: true }都可以;
// 3、createObjectStore第二个参数里加 { keyPath: "name" },这里不能再在objectStore.add(item)里面添加第二个参数,即使这里第二个参数添加的和createObjectStore里面的第二个参数的keyPath的一致;

上面的只影响user对象存储里面的排序,其它索引的排序只和自己的索引有关;

3、查找数据
1、通过特定值获取数据(只能获取单条数据)
  • 这里默认只能获取通过createObjectStore的第二参数的keyPath设置的参数的user对象存储的数据,其它索引的无法查出;
  • 或者使用index方法改变默认索引,比如let store = objectStore.index(“age”),再用store.get(18)就可以通过age来查询了(前提是用createIndex创建了age索引的对象存储,才能使用objectStore.index(“age”),才能查询);
var request = window.indexedDB.open('people', 1);

request.onsuccess = function (event) {
    var db = event.target.result;

    var transaction = db.transaction(['user'], 'readwrite');

    var objectStore = transaction.objectStore('user');

    var request = objectStore.get(1);

    request.onsuccess = function (event) {
        //打印搜索的结果
        console.log(e.target.result);
    };

    request.onerror = function (event) {
        // 错误处理!
    };
}
2、通过游标获取数据(获取多条数据)

当你需要遍历整个存储空间中的数据时,你就需要使用到游标,与传统数据库查询不同,游标不会事先收集所有结果。相反,游标指向 第一个结果,并在接到指令前不会主动查找下一条数据

var request = window.indexedDB.open('people', 1);

request.onsuccess = function (event) {
    var db = event.target.result;

    var transaction = db.transaction(['user'], 'readwrite');

    var objectStore = transaction.objectStore('user');

    var request = objectStore.openCursor();

    request.onsuccess = function (event) {
        var cursor = event.target.result;
        if (cursor) {
            console.log(cursor.key, cursor.value);
            cursor.continue();
        }
    };

    request.onerror = function (event) {
        // 错误处理!
    };
}

使用游标时有一个需要注意的地方,当游标遍历整个存储空间但是并未找到给定条件的值时,仍然会触发onsuccess函数。

openCursoropenKeyCursor有两个参数:**openKeyCursor**遍历出来的值里面没有value对象值,其它和openCursor一致

  1. 第一个参数(占位时可以使用null),遍历范围,指定游标的访问范围。该范围通过一个IDBKeyRange参数的方法来获取。 遍历范围参数具体示例如下: ===>这种键范围只能比较其键能比较大小的对象存储或者only这种
// 匹配值 key === 1 
const singleKeyRange = IDBKeyRange.only(1);
// 匹配值 key >= 1,lowerBound用于设定结果集的下限,闭集
const lowerBoundKeyRange = IDBKeyRange.lowerBound(1);  
// 匹配值 key > 1,lowerBound用于设定结果集的下限,包含该值,设置第二个参数为true时,变为开集
const lowerBoundOpenKeyRange = IDBKeyRange.lowerBound(1, true); 
// 匹配值 key < 2,upperBound用于设定结果集的上限,包含该值,设置第二个参数为true时,变为开集
const upperBoundOpenKeyRange = IDBKeyRange.upperBound(2, true);
// 匹配值 key >= 1 && key < 2,指定一个左右范围
const boundKeyRange = IDBKeyRange.bound(1, 2, false, true);  
index.openCursor(boundKeyRange).onsuccess = function(event) {   
    const cursor = event.target.result;   
    if (cursor) {     
        // Do something with the matches.     
        cursor.continue();   
    } 
};  
  1. 第二个参数,默认值是next,遍历顺序,指定游标遍历时的顺序和处理相同id(keyPath属性指定字段)重复时的处理方法。改范围通过特定的小写字符串(IDBCursor的常量已经弃用)来获取。其中:
  • next,从前往后获取所有数据(重复值也会遍历出来)
  • prev,从后往前获取所有数据(重复值也会遍历出来)
  • nextunique,从前往后获取数据(重复数据只取第一条,索引重复即认为重复,下同)
  • prevunique,从后往前获取数据(重复数据只取第一条)
var request = window.indexedDB.open('test', 1);

request.onsuccess = function (event) {
    var db = event.target.result;

    var transaction = db.transaction(['user'], 'readwrite');

    var objectStore = transaction.objectStore('user');

    var lowerBoundOpenKeyRange = IDBKeyRange.lowerBound(1, false);
    var request = objectStore.openCursor(lowerBoundOpenKeyRange, "prev");

    request.onsuccess = function (event) {
        var cursor = event.target.result;
        if (cursor) {
            console.log(cursor.value);
            cursor.continue();
        }
    };

       request.onerror = function (event) {
        // 错误处理!
    };
}
4、使用索引

在前面构建数据库时,我们创建了所有的索引。现在我们也可以通过索引来进行数据检索。他的本质还是通过之前获取数据的API来进行,只是将原来使用的keyPath属性转换成为了索引指定的属性。

var request = window.indexedDB.open('test', 1);

request.onsuccess = function (event) {
 var db = event.target.result;

 var transaction = db.transaction(['user'], 'readwrite');

 var objectStore = transaction.objectStore('user');

 // 使用索引
 var index = objectStore.index('name');

 // 第一种,get方法
 index.get('a').onsuccess = function (event) {
     console.log(event.target.result);
 }

 // 第二种,普通游标方法
 index.openCursor().onsuccess = function (event) {
     console.log('openCursor:', event.target.result.value);
 }

 // 第三种,键游标方法,该方法与第二种的差别为:普通游标带有value值表示获取的数据,而键游标没有
 index.openKeyCursor().onsuccess = function (event) {
     console.log('openKeyCursor:', event.target.result.key);
 }
}
5、修改数据===>修改时,须带上这条数据的索引键

注:put方法不仅能够修改现有数据,也能够往存储空间中增加新的数据。

使用objectStore.put方法时,参数为已存在的键,即为修改,为不存在的键时,即为增加;

这里不能像查询一样,通过store.index()来修改索引,index上只有get方法

var transaction = db.transaction(['user'], 'readwrite');
var store = transaction.objectStore("user");

// 用put增加一条新数据
var request1 = store.put({
    id: 5,
    name: "李志聪",
    age: 22,
    sex: "man",
    addTime: "2021-2-5"
});

// 用put增加一条新数据,改sex描述===>是修改时,须带上这条数据的索引键
var request2 = store.put({
    id: 2,
    name: "lzc",
    age: 18,
    sex: "男",
    addTime: "2021-2-2"
});

request1.onsuccess = function (event) {

}
6、删除数据
var transaction = db.transaction(['user'], 'readwrite');
var store = transaction.objectStore("user");

var request = store.delete(对应某一条keyPath值);

request.onsuccess = function (event) {
    
}
7、关闭数据库
// 比如在destoryed钩子里面可以关闭数据库
db.close();

五、安全相关

IndexedDB也受到浏览器同源策略的限制。

六、dexie.js库的使用

dexie.js:A Minimalistic Wrapper for IndexedDB

基于indexDB的Dexie数据库

// 下面配一个简单的演示

// 创建一个数据库 若数据库已存在则为打开
// 打开数据库时,会判断当前version值是否大于已经存在的version值,若大于则会upgrade即升到最高版本
var db = new Dexie("mydb");

// 设定版本,添加一个person表,里面有自增的id主键,有name和age两个索引
// 注意:不要像在SQL中那样声明所有列。只声明要索引的属性,即要在where(…)查询中使用的属性。
db.version(1).stores({
    person: "++id, name, age"
})

// 增加(还是使用上面的数据进行存储)
for(let item of data) {
    db.person.add(item)
}

// 修改
setTimeout(() => {
    db.person.put({
        id: 2,
        name: "聪波",
        age: 18,
        sex: "boy",
        addTime: "2021-2-2"
    })
    console.log(db.person.get(2)) // 一个promise对象
    // 普通查询
    db.person.get(2).then(res => {
        console.log("查询的结果为===>", res)
    })
}, 1000)

// 带条件查询
setTimeout(() => {
    // adove、aboveOrEqual、below、belowOrEqual、between、equals
    db.person.where("age").aboveOrEqual(18).toArray().then(res => {
        console.log("年龄大于等于18岁的有===>", res)
    })
}, 2000)

// 删除
setTimeout(() => {
    // 删除第一条
    db.person.delete(1);
    db.person.get(1).then(res => {
        console.log("第一条数据===>", res)
    })
}, 3000)

setTimeout(() => {
    db.close();
    console.log("要是数据库没有关闭,下面将打印第三天数据");
    db.person.get(3).then(res => {
        console.log("第三条数据===>", res)
    })
}, 4000)

你可能感兴趣的:(识记,js,indexedDB)