第一个Web存储的技术叫做Cookie,它是网站的身份证。是网站为了辨别用户身份,进行session(服务端的session)跟踪而存储在用户本地终端上的数据,也就是说它是存在电脑硬盘上的,一个很小的txt类型的文件。Cookie每次都会跟随http请求发送到服务端,也就是说每一个http请求都会带上我们的cookie数据,因此它存在一个安全性的问题。
cookie本身也是有很大的局限性的,首先它很小,主流的浏览器最大支持 4096 字节,除了最大字节的限制,每个网站的cookie个数(也就是每一个first每一个域)也是有限制的,一般浏览器是20个。除此之外,cookie还会默认跟随所有http请求发送,即使不需要使用这个cookie来鉴别用户但是它也是会跟随http请求发送的,这样就会造成一个网络资源的浪费。然后部分的浏览器还限制了总的cookie个数300个。
在cookie的诸多局限性下,Web Storage应运而生。Web Storage 解决了很多问题:
比如它支持存储大量数据,支持复杂的本地数据库,而且也不会默认跟随http请求。Web Storage主要是有四个:
Cookie是html4的一个标准,它一般不需要考虑兼容。它是网站的一个身份证,服务器可以针对不同用户,做出不同的响应。cookie存储在用户的机器上是一个纯文本,就是一个txt文件并不是一个脚本,它不能执行东西只负责记录。浏览器每次请求都会带上当前网站的cookie。
Cookie分为两种类型,一种呢是会话cookie,也就是临时性的cookie,退出浏览器或者是关闭即删除;
另一种叫持久cookie,它会一直存在,存在的时间由特定的过期时间或者是有效期来决定。
Cookie的域 Domain决定了当前的一个cookie的权限,哪一个域可以使用这个cookie。
Cookie的路径 Path,下面一个简单的例子:
www.baidu.com id="123456" domain="www.baidu.com" www.baidu.com/user id="123456" user="eric" domain="www.baidu.com" path="/user/" www.baidu.com/search id="123456"; www.baidu.com/user/search id="123456" user="eric";
如上www.baidu.com设置了一个id等于123456,domain是www.baidu.com,然后另外一个跟第一个一样多设置了一个user,id相同,但是多了一个user=“Eric”,它的domain设置成了www.baidu.com,path就到了user下面。这两者设置完成之后,当我们访问www.baidu.com/search时百度只能拿到id,因为user="Eric"是属于user这个域下面的,也就是说在search下面是获取不到的,但是在www.baidu.com/user/search这个时候我们就可以获取到名叫Eric的user。Path也是一种权限的控制只是相较于域domain是低一级的。
Cookie的安全secure,如果这个属性为TRUE,那么网站只有在https的请求下面才会携带当前的cookie。
Cookie的HttpOnly这个属性如果为TRUE,那么就不允许JAVAScript操作cookie。
因为cookie是存储在客户端一个独立的文件,因此服务器是无法分辨用户和攻击者的。关于cookie的目的分为两种:一种是跨站点脚本攻击,一种是跨站请求伪造。
key-value的键值对,是HTML5新增的一个会话存储对象。
SessionStorage是临时保存在同一窗口,也就是同一标签页的数据。如果当前标签页关闭了,那么SessionStorage也就失效了。这也是SessionStorage最显著的一个特点:单页标签限制。
除此之外,它还有的一些特点有:
属性:
Json对象
LocalStorage也是在浏览器的Application下面有一个Local Storage,它和SessionStorage是十分相似的,同样是key-value键值对,也是HTML5的新增存储对象,它与SessionStorage的特点不同之处在于没有标签页的限制和在浏览器的无痕模式下LocalStorage是不允许读取的,永久性的存储,然后SessionStorage超出限制是覆盖不会报错而LocalStorage超出会报错。
特点**:
属性:
注意事项:LocalStorage和SessionStorage在web view是不可靠的,web view指的是在开发混合APP的时候使用了浏览器来实现我们的APP,这个时候是不可靠的,因为在浏览器崩溃的情况下数据可能没有存进去。
另外一个在IOS浏览器中不可重复setItem,如果重复会报错,然后这个时候我们需要先removeItem再添加item。
监听storage的变化
监听storage包括SessionStorage和LocalStorage。然后这里需要提到两个概念:同源和监听同源网页。
http://localhost:63342/simpleApp/app/index.html#/ (协议) (域名) (端口) (路径)
window.addEventListener("storage", function (event) { console.log(event.key); console.log(event.oldValue); console.log(event.newValue); console.log(event.url); console.log(event.storageArea); });
IndexedDB 背景
基本概念
首先它是一个NoSQL,也就是一个非关系型数据库。MySQL和Oracle都是关系型数据库。意思就是说如果建立了两个表在关系型数据库里面我们可以通过一个外链把多个表联系起来,但是NoSQL不行,在NoSQL里面如果想要多个表关联起来,我们只能手动的在关联的表里面添加上需要关联的另外一个或多个表的id。这是NoSQL与MySQL两者之间的一个区别。
IndexedDB的特点也是和Storage是一样的:
IndexedDB几个基本概念:
IndexedDB浏览器兼容
IDBDatabase
IDB是IndexedDB的缩写,它呢就是数据库,数据库也叫作数据的一个容器。每一个源(同源策略)可以建立很多数据库。Database有一个版本的概念,版本对应着数据库表,同一时刻只能存在一个版本。比如:新增一个表,然后我们需要把database的版本加一,表里面要新增一列,这时同样需要把数据库版本加一。
注意:1 同一时刻只能有一个版本存在
2 修改数据库结构只能通过升级数据库版本
/* databaseName不存在则创建 */ /* version为整数, 新建时为1 */ let database; let userStore; const request = window.indexedDB.open(databaseName, version); /* 成功打开数据库 */ request.onsuccess = event => { database = request.result; } /* 打开数据库失败 */ request.onerror = error => { console.log(error); } /* 版本号大于当前数据库版本 */ request.onupgradeneeded = event => { database = event.target.result; }
注意:如果在打开数据库时,数据库不存在,将会新建一个
IDBObjectStore(数据库表)
创建表,最好是在upgradeneeded下执行;在创建数据库表的时候需要指定主键,主键代表了唯一的标识,比如 keyPath:‘id’;如果不指定主键,我们可以指定一个autoIncrement:true,自增的一个概念,也就是不指定主键数据库会自动添加主键而且这个主键就是数字,依次递增的。
const createStore = () => { //如果当前的objectStoreNames.contains包含user,如果不包含user这个表,然后就用这个database.createObjectStore创建了一个表,这个表的名字就叫做user,然后主键就是下面的id if(!db.objectStoreNames.contains('user')) { userStore = database.createObjectStore('user', { keyPath: 'id' }); } }
指定索引:
const createStore = () => { if(!database.objectStoreNames.contains('user')) { userStore = database.createObjectStore('user', { keyPath: 'id' }); userStore.createIndex('name', 'name', { unique: true }); } }
IDBTransaction(事务)
创建完之后需要往里面添加数据,添加数据我们就需要使用到事务。
事务涉及到数据库的增删改查,它有三个状态:
属性:
数据库的基本操作:增删改查以及清空。
新增数据(add)
分为两种情况:一种是使用自增的数据库的id或者是自增的一个键值,如果已经创建主键,那么新增必须包含主键和另一种已创建主键但主键不可重复。
const add = () => { /* 创建事务 */ /* 使用某个数据库 */ /* add新增 */ transactionRequest = database.transaction(['user'], 'readwrite') .objectStore('user') .add({ id: 100, name: 'Eric', age: 28, email: 'Ericlee00@163.com' }); /* 成功 */ transactionRequest.onsuccess = event => { console.log('数据写入成功', event); }; /* 失败 */ transactionRequest.onerror = error => { console.log('数据写入失败', error); } }
读取数据(get)
const read = () => { /* 创建事务 */ transaction = database.transaction(['user']); /* 选择数据库表 */ table = transaction.objectStore('user'); /* 读取数据 */ transactionRequest = table.get(2); /* 成功 */ transactionRequest.onerror = event => { console.log('数据读取失败', event); }; /* 失败 */ transactionRequest.onsuccess = event => { if (transactionRequest.result) { console.log('数据读取成功', transactionRequest.result); } else { console.log('未读取到数据'); } }; }
更新数据(put)
更新不存在的数据时会新建,也就是说在新增数据时如果相同,往往会出错,但是在更新数据时不会出错。如果数据不存在就会新建,如果存在就会一直更新。
const update = () => { transactionRequest = database.transaction(['user'], 'readwrite') .objectStore('user') .put({ id: count, name: 'David', age: 35, email: 'David@xiakedao.com' }); transactionRequest.onsuccess = function (event) { console.log('更新数据成功', event); }; transactionRequest.onerror = error => { console.log('更新数据失败', error); } }
删除数据(delete)
const delete = () => { transactionRequest = database.transaction(['user'], 'readwrite') .objectStore('user') .delete(2); transactionRequest.onsuccess = function (event) { console.log('删除数据成功', event); }; transactionRequest.onerror = error => { console.log('删除数据失败', error); } }
清空数据(clear)
IDBCursor(指针)
提供了一种遍历数据的可能。
const readAll = () => { table = database.transaction('user').objectStore('user'); table.openCursor().onsuccess = () => { let cursor = event.target.result; if (cursor) { console.log('数据遍历', cursor); cursor.continue(); } else { console.log('数据遍历完成'); } }; }
关闭IndexedDB数据库连接
const closeDataBase = () => { database.close(); }
删除IndexedDB数据库前,须先关闭数据库连接
const deleteDataBase = () => { indexedDB.deleteDatabase('first_database'); }
基本概念:并不是 HTML5 的规范 , 只能算是一个独立的规范;使用WebSQL是完完全全的SQL 语句,使用SQL语句来操作客户端数据库;它一共有三个比较重要的概念,分别是:openDatabase 打开数据库,可以是使用现有数据库或者新建数据库;transaction 事务,所有的数据库都支持事务;executeSql 执行SQL语句。
openDatabase(打开数据库)
相比于IndexedDB的概念稍微多一点,主要是有数据库名称、版本号(在IndexedDB里面版本号都是整数,但是在WebSQL里面它可以是小数)、描述文本(介绍数据库是干什么的)、数据库大小和创建回调(function,只在第一次创建的时候才会调用)。
const database = openDatabase('my_database', '1.0', 'first', 2 * 1024 * 1024, function() { });
Transaction(事务)
const createTable = () => { database.transaction(function (content) { content.executeSql('CREATE TABLE IF NOT EXISTS USER (id unique, name)'); }); }
const addData = () => { database.transaction(function (content) { content.executeSql('INSERT INTO USER (id, name) VALUES (1, "Eric")'); }); }
const searchData = () => { database.transaction(function (content) { content.executeSql('SELECT * FROM USER'); }); }
const updateData = () => { database.transaction(function (content) { content.executeSql('UPDATE USER SET name='David' WHERE id=1'); }); }
const deleteDataBase = () => { database.transaction(function (content) { content.executeSql('DROP TABLE USER'); }); }