存储本地_项目实战之本地存储篇
在前端项目开发中,前端的本地存储是必不可少的,今天小编就前端的本地存储在项目中的使用详细的介绍一下。前端本地存储主要有:
- cookie
- localStorage
- sessionStorage
- webSQL/indexDB
接下来就这几种前端常用的存储方式进行介绍。
cookie
cookie就是存储在客户端的一小段文本,大小不能超过4kb,在请求接口的时候,cookie会被请求携带着,进而被服务器所读取使用。打开浏览器控制台,F12>>Application>>Cookies,随便选择一个域,我们可以看到里面有很多cookie,如下所示:
主要属性
- Name
cookie的名称
- Value
cookie的值,大小最大4Kb
- Domain
cookie存储的域名
- Path
cookie存储的路径
- Size
cookie的大小
- Expires/Max-Age
这两个属性涉及到 cookie 的存活时间
Expires 属性指定一个具体的到期时间,到了这个指定的时间之后,浏览器就不再保留这个 cookie ,它的值是 UTC 格式,可以使用 Date.prototype.toUTCString() 格式进行转换。
Max-Age 属性制定了从现在开始 cookie 存在的秒数,比如 60 * 60 (即一小时)。过了这个时间以后,浏览器就不再保留这个 Cookie。
Max-Age的优先级比Expires高,如果两者都不设置,则这个cookie会在浏览器关闭的时候失效。
- HttpOnly
如果设置了该属性,意思就是这个cookie不能被JavaScript取到,也就防止了cookie被脚本读取,然后当发起请求的时候,该cookie才会被带上。
- Secure
指定浏览器只有在加密协议 HTTPS 下才能发送cookie,不需要设置,当协议是https时,会自动开启。
使用方式
- 设置cookie
/** * 设置cookie * @param {*} key 名称 * @param {*} val 值 * @param {*} time 失效时间 */
export const setCookie = (key, val, time) => {
var date = new Date();
var expiresDays = time;
//将时间转换为cookie设置时间的格式
date.setTime(date.getTime() + expiresDays * 24 * 3600 * 1000);
document.cookie = key + "=" + val + ";expires=" + date.toDateString();
}
- 获取cookie
/** * 获取cookie * @param {*} key 名称 */
export const getCookie = (key) => {
var getCookie = document.cookie.replace(/[ ]/g, "");
var arrCookie = getCookie.split(";")
var tips;
for (var i = 0; i var arr = arrCookie[i].split("=");
if (key == arr[0]) {
tips = arr[1];
break;
}
}
return tips;
}
- 删除cookie
删除cookie的话,可以直接调用设置cookie的方法,将失效时间置为-1,如下:
setCookie(key,'',-1)
localStorage/sessionStorage
localStorage/sessionStorage是在html5中新加入的技术,两者除了数据的时效性不一样之外,其他都一样。大小一般为5MB,存储的时候,仅仅在客户端存储,不会随着请求的调用而传递到服务器。
localStorage不手动删除则永久有效,sessionStorage仅在当前会话有效
下面F12>>Application>>Cookies看一个存储示例:
可以看到,其只有两个属性,也就是key(名称)、value(值)
使用方式
localStorage和sessionStorage都具有相同的操作方法,例如setItem、getItem和removeItem等,为了使用方便,我们对其进行二次封装,示例如下:
- 存储Storage
/** * 存储Storage */export const setStore = (params = {}) => { let { name,//名称 content,//内容 type,//类型 } = params; let obj = { dataType: typeof (content), content: content, type: type, datetime: new Date().getTime() } if (type) window.sessionStorage.setItem(name, JSON.stringify(obj)); else window.localStorage.setItem(name, JSON.stringify(obj));}
- 获取Storage
/** * 判断是否为空 */function validatenull (val) { if (typeof val === 'boolean') { return false } if (typeof val === 'number') { return false } if (val instanceof Array) { if (val.length == 0) return true } else if (val instanceof Object) { if (JSON.stringify(val) === '{}') return true } else { if (val == 'null' || val == null || val == 'undefined' || val == undefined || val == '') return true return false } return false}
/** * 获取Storage */export const getStore = (params = {}) => { let { name,//名称 debug//是否需要转换类型 } = params; let obj = {}, content; obj = window.sessionStorage.getItem(name); if (validatenull(obj)) obj = window.localStorage.getItem(name); if (validatenull(obj)) return; try { obj = JSON.parse(obj); } catch{ return obj; } if (debug) { return obj; } if (obj.dataType == 'string') { content = obj.content; } else if (obj.dataType == 'number') { content = Number(obj.content); } else if (obj.dataType == 'boolean') { content = eval(obj.content); } else if (obj.dataType == 'object') { content = obj.content; } return content;}
- 删除Storage
/** * 删除localStorage */export const removeStore = (params = {}) => { let { name, type } = params; if (type) { window.sessionStorage.removeItem(name); } else { window.localStorage.removeItem(name); }
}
- 获取全部Storage
/** * 获取全部Storage */export const getAllStore = (params = {}) => { let list = []; let { type } = params; if (type) { for (let i = 0; i <= window.sessionStorage.length; i++) { list.push({ name: window.sessionStorage.key(i), content: getStore({ name: window.sessionStorage.key(i), type: 'session' }) }) } } else { for (let i = 0; i <= window.localStorage.length; i++) { list.push({ name: window.localStorage.key(i), content: getStore({ name: window.localStorage.key(i), }) })
} } return list;
}
- 清空全部Storage
/** * 清空全部Storage */export const clearStore = (params = {}) => { let { type } = params; if (type) { window.sessionStorage.clear(); } else { window.localStorage.clear() }
}
cookie、localStorage、sessionStorage异同
数据存储时间
- cookie 可以自己设置失效时间
- localStorage 不主动清除,则永久存储
- sessionStorage 当前页面关闭时被删除
大小
- cookie 最大4kb
- localStorage 最大5MB
- sessionStorage 最大5MB
请求是否携带
- cookie 每次请求会携带在请求头中
- localStorage 不携带,仅在客户端存储
- sessionStorage 不携带,仅在客户端存储
易用性
- cookie 原生api使用不友好,需自己二次封装
- localStorage 原生接口可使用,也可以自己二次封装
- sessionStorage 原生接口可使用,也可以自己二次封装
个人推荐在项目中使用storage存储,cookie存储数据过多,会造成性能问题。当然,大家可以根据实际情况进行选择,二次封装方法已双手奉上。
webSQL/indexDB
对于简单的数据存储,storage和cookie就已经够用了,但是如果需要存储比较复杂的关系型数据,再使用storage和cookie,就有点力不从心了。这个时候可以使用webSQL或者indexDB进行存储。
webSQL
Web SQL数据库API是一个独立的规范,在浏览器层面提供了本地对结构化数据的存储,已经被很多现代浏览器支持了。
核心api
- openDatabase() => 用来打开或创建数据库(没有时则创建,有则打开)
- transaction() => 这个方法可以控制一个或多个事务,以及基于这种情况提交或者回滚
- executeSql() => 用于执行实际的 SQL 查询
判断浏览器是否支持该功能
从上面的图中可以看出,webSQL兼容性并不是太好,因此使用时,我们需要先判读那浏览器是否支持。
if (window.openDatabase) { // 操作 web SQL } else { alert('当前浏览器不支持 webSQL !!!');}
webSQL操作类封装
webSQL操作类封装代码量较大,此处就不再展示,需要的小伙伴可以关注我公众号回复【webSQL操作类】获取。下面给个简单的例子:
var myDB = { name: 'formData', version: 1, db: null,};myDB.db = openDatabase(myDB.name, myDB.version, 'test', 100 * 1024 * 1024);myDB.db.transaction(function(tx) { tx.executeSql('', [], function(tx, result) { if(result.rows.length!=0){ //result.rows.item(i) } }, function(tx, error) { console.log(error); });})
常用的SQL语句:
//新建表'CREATE TABLE IF NOT EXISTS 表名 (列名称1 PRIMARY KEY,列名称2 UNIQUE ,列名称3)'//删除表'DROP TABLE 表名'//清空表'DELETE FROM 表名'//删除条目'DELETE FROM 表名 WHERE 列名称1 = ? and 列名称2 = ?'//新增一条'INSERT INTO 表名 VALUES (?,?,?,?,?,?,?)' //为所有列添加值'INSERT INTO 表名 (列名称2,列名称4,列名称6) VALUES (?,?,?)' //为指定列添加值//批量增加insert into persons (id_p, lastname , firstName, city )values(200,'haha' , 'deng' , 'shenzhen'),(201,'haha2' , 'deng' , 'GD'),(202,'haha3' , 'deng' , 'Beijing')//更新一条'UPDATE 表名 SET 列名称1 = ? where 列名称2 = ? AND 列名称3 = ?''UPDATE 表名 SET 列名称1 = ?,列名称2 = ?,列名称3 = ? where 列名称2 = ? AND 列名称3 = ?' //根据主键存在与否,更新或添加一条数据'replace into 表名 (列名称1,列名称2,列名称3,列名称4,列名称5) VALUES (?,?,?,?,?) ' //查找(更多查询请根据自己的需要自由组合)'select * from 表名 where 列名称1 = ? and 列名称1 >= ?' //常规查找'select * from 表名 where 列名称1 = ? or 列名称1 >= ?' //常规查找
'select * from 表名 ORDER BY ?' //指定排序项'select * from 表名 ORDER BY ? LIMIT 2;'//只查找符合条件的2条
WHERE 列名称 IS NOT NULL //非空WHERE 列名称 LIKE "111%" //111开头的WHERE 列名称 LIKE "%111" //111结尾的WHERE 列名称 LIKE "%111%" //包含111的WHERE 列名称 NOT LIKE "%111%" //不包含111的'_a_' //三位且中间字母是a的'_a' //两位且结尾字母是a的'a_' //两位且开头字母是a的
WHERE 列名称 GLOB > 111 //大于111WHERE 列名称 GLOB >= 111 //大于等于111WHERE 列名称 GLOB != 111 //不等于111
WHERE 列名称 GLOB '111*' //111开头的WHERE 列名称 IN ( 25, 27 ) //值为25或27的WHERE 列名称 NOT IN ( 25, 27 ) //值不为25或27的WHERE 列名称 BETWEEN 25 AND 27 //值在25到27之间的WHERE 列名称 IN ( '25', '27' ) //注意:拼接sql时不要忘记引号
//索引'CREATE INDEX IF NOT EXISTS 索引名 on 表名 (列名称1, 列名称2) ''DROP INDEX 索引名'
indexDB
IndexedDB标准是HTML5官方认可的本地数据库解决方案。其目的不是取代服务器端数据库,它在一些特定场景下很有用,比如离线应用。IndexedDB是一种轻量级NOSQL数据库,是由浏览器自带。相比Web Sql更加高效,包括索引、事务处理和查询功能。
从上图可以看出indexDB的兼容性还是不错的。
使用indexDB
创建/打开一个数据库
首先我们需要创建或者打开一个数据库对象,可以使用window.indexedDB.open()方法,示例如下:
var openRequest =window.indexedDB.open(name, version);var db;openRequest.onupgradeneeded = function(e) { console.log("Upgrading...");}openRequest.onsuccess = function(e) { console.log("Success!"); db = e.target.result;}openRequest.onerror = function(e) { console.log("Error"); console.dir(e);}
第一次打开数据库时,会先触发upgradeneeded事件,然后触发success事件
open方法返回的是一个对象(IDBOpenDBRequest),回调函数定义在这个对象上面
回调函数接受一个事件对象event作为参数,它的target.result属性就指向打开的IndexedDB数据库
创建一个存放数据的“对象仓库”
数据库对象有了,我们还需要创建一个存放数据的“对象仓库”,示例如下:
db.createObjectStore("test", { keyPath: "email" });
db.createObjectStore("test2", { autoIncrement: true });
keyPath表示的是存储数据的键名,autoIncrement表示是否使用自动递增的整数作为键名。一般来说,两个属性有一个就可以了。
创建一个数据库事务对象
transaction方法用于创建一个数据库事务。向数据库添加数据之前,必须先创建数据库务。
transaction方法返回一个事务对象,该对象的objectStore方法用于获取指定的对象仓库。
var transaction = db.transaction(["firstOS"],"readwrite");
var store = transaction.objectStore("firstOS");
transaction方法接受两个参数:
第一个参数是一个数组,里面是所涉及的对象仓库,通常是只有一个;
第二个参数是一个表示操作类型的字符串。readonly(只读)和readwrite(读写);
transaction方法有三个事件,可以用来定义回调函数。
abort: 事务中断; complete: 事务完成; error: 事务出错。
transaction.oncomplete = function(event) { // some code};
操作数据
transaction对象提供了一些api,供我们操作数据。
- 添加数据 add()
获取对象仓库以后,就可以用add方法往里面添加数据了,示例如下:
var transaction = db.transaction(["firstOS"],"readwrite");var store = transaction.objectStore(“firstOS”);var data = {name: 'monkey'};var request = store.add(data,1);request.onerror = function(e) { console.log("Error",[e.target.error.name](http://e.target.error.name));}request.onsuccess = function(e) { console.log("数据添加成功!");}
add方法的第一个参数是所要添加的数据,第二个参数是这条数据对应的键名(key),上面代码将对象o的键名设为1。如果在创建数据仓库时,对键名做了设置,这里也可以不指定键名。
- 更新数据 put()
var data = { name: 'monkeysoft' };var request = store.put(data);
- 读取数据 get()
var request = store.get(key);
- 删除数据 delete()
var request = store.delete(key);
- 清空数据库 clear()
var request = store.clear();
- 遍历数据 openCursor()
var request = store.openCursor();
indexDB操作类封装
indexDB操作类封装代码量较大,此处就不再展示,需要的小伙伴可以关注我公众号回复【indexDB操作类】获取
以上就是我对前端本地存储的一些理解和整理,如有错,欢迎各位大佬指正,免得误人子弟~嘿嘿。
参考: 1、indexDB讲解与封装 https://www.jianshu.com/p/136c268b8559
点击留言
历史好文推荐:
1、【整理分享】你需要的资源(更新版)
2、【万字长文】史上最强JavaScript总结
3、【万字长文】史上最强vue总结,更新版
4、【万字长文】史上最强css、html总结~看完涨薪不再是梦
5、35个前端常用工具函数,建议收藏
❤️爱心三连击
1.看到这里了就点个在看支持下吧,你的「在看」是我创作的动力。
2.关注公众号
小猴子的web成长之路,「一起玩转前端」!
3.特殊阶段,带好口罩,做好个人防护。
4.可以添加我微信【monkeysoftweb】,拉你进技术交流群一起学习。
“在看转发”是最大的支持
存储本地_项目实战之本地存储篇相关推荐
- Android视频《手机影音_项目实战》-杨光福-专题视频课程
Android视频<手机影音_项目实战>-49877人已学习 课程介绍 手机影音项目是真实的上线项目,本视频在原项目基础上,进行了新技术的更新和优化.该项目包括本地音乐播放 ...
- Python和Java结合的项目实战_[项目实战] Python高级教程项目实战篇 Python和Java结合的项目实战 视频教程 [...
资源介绍 课程简介:xa0xa0 Python高级教程项目实战篇 Python和Java结合的项目实战 视频教程 教学视频 ----------------------课程目录 Python项目实战篇 ...
- 双y轴设置 颜色_项目实战:Qt多段Y轴折线图框架(双Y轴段折线、支持拽拖、浮动游标显示X值各段Y值、实时下位机数据)...
若该文为原创文章,转载请注明原文出处 本文章博客地址:https://blog.csdn.net/qq21497936/article/details/111660400长期持续带来更多项目与技术分享 ...
- 千里眼摄像头支持对象存储吗_为什么建议大家使用对象存储?我总结了这六点...
对象存储可以简单理解为用来存储图片.音频.视频等非结构化数据的数据池.相对于主机服务器,具有读写速度快,利于分享的特点.我为什么建议大家使用对象存储?我总结了这六点. 1.网站数据动静分离,大幅提升网 ...
- android 保存退出之前的页面_项目实战:Qt+Android模拟操作器(模拟操作app,打开,点击,输入,获取验证码等等)...
若该文为原创文章,转载请注明原文出处 本文章博客地址:https://blog.csdn.net/qq21497936/article/details/109313803 各位读者,知识无穷而人力有穷 ...
- ffmpeg 获取帧率_项目实战:Qt+FFmpeg录屏应用(支持帧率、清晰度设置)
若该文为原创文章,转载请注明原文出处 本文章博客地址:https://blog.csdn.net/qq21497936/article/details/109827936 各位读者,知识无穷而人力有穷 ...
- java使用xml存储数据_聊一聊 Redis 数据内部存储使用到的数据结构
Redis 数据库虽然一直都在使用,但是对其内部存储结构之类的,都没有研究过,哪怕是面试的时候都没有准备过这方面的东西.最近在看一门网课,里面有讲到过这一块的内容,结合了<Redis 设计与实现 ...
- app inventor调用图像识别_项目实战-图像识别项目-通过QT制作图形界面并调用百度AI进行图像识别(一)...
转自迅为4412开发板项目实战教程 硬件平台:iTOP-4412开发板 项目名称:图像识别项目 本文我们来学习利用QT构建一个图形界面并用QT调用百度AI的接口 一.添加arm编译套件 打开QT cr ...
- python中文件的存储类型_关于python中数据存储大总结,涵盖文件系统和数据库存储两种方法-文件系统类型...
存储数据是python必不可免的话题,数据的存储类型也多种多样,文件系统存储(.txt..csv..json.多媒体存储).关系型数据库存储(MySQL等).非关系型数据库存储(MongoDB).今天 ...
最新文章
- web.config中sessionState节点的配置方案
- iPhone销售额下滑12%,但AirPods和手表救了苹果
- windows启动管理器_win7系统任务管理器的五种打开方式,很实用,学习一下
- 2020年终总结暨组会PPT20201229《复现chen密度径向分布结果》
- C++中int id[sizeof(unsigned long)]的语句,正确吗?
- 《大话数据结构》一些基础知识
- 数据库中主键和外键的设计原则
- .NET Core开发日志——简述路由
- [转载]Oracle ltrim() 函数用法
- MySQL幻读及解决方法
- 支撑全网70%世界杯流量 盘点世界杯直播背后的阿里云黑科技
- 计算机应用基础选择题综合十,计算机应用基础选择题综合复习练习题
- Error: failed to unmarshal json. invalid character '\'' looking for beginning of value解决方案
- WAMP安装curl扩展并发起https请求
- 公司买网络设备,至少16口
- 管理感悟:管理人员要不要技术好
- (2) 怎么学习IFC (Industry Foundation Class)
- postman变量设置及脚本的使用
- Android Studio配置优化最全详解
- 小高不太行之前端--JSON