前端数据存储

记录一些前端数据存储的方法!



JS文件

把一些常用数据(json对象、字符串等)保存在js文件中,通过script标签引入使用。


创建

创建js文件


引入

script引入js文件。./代表当前目录,../代表上级目录。


使用

使用js文件中的数据、变量、函数、类等。


扩展

vue-cli开发的项目中,想在.vue文件中导入js文件。笔记见:VUE导入js文件



Storage API

Web Storage 包含如下两种机制:

  • sessionStorage 为每一个给定的源(given origin)维持一个独立的存储区域,该存储区域在页面会话期间可用(即只要浏览器处于打开状态,包括页面重新加载和恢复)。
  • localStorage 同样的功能,但是在浏览器关闭,然后重新打开后数据仍然存在(大小限制通常在 2.5-10M之间)。

案例

localStorage案例,给localStorage设置过期时间

封装Storage类

封装Storage类,可以保存在单独的js文件中,通过script标签引入使用。

class Storage {
	constructor(key) {
		this.key = 'storage';
	}
	//设置缓存
	setItem(params) {
		let obj = {
			key: '',
			value: '',
			expires: "",
			startTime: new Date().getTime() //记录何时将值存入缓存,毫秒级
		}
		let options = {};
		//将obj和传进来的params合并
		Object.assign(options, obj, params);
		if (options.expires) {
			//如果options.expires设置了的话
			//以options.key为key,options为值放进去
			localStorage.setItem(options.key, JSON.stringify(options));
		} else {
			//如果options.expires没有设置,就判断一下value的类型
			let type = Object.prototype.toString.call(options.value);
			//如果value是对象或者数组对象的类型,就先用JSON.stringify转一下,再存进去
			if (Object.prototype.toString.call(options.value) == '[object Object]') {
				options.value = JSON.stringify(options.value);
			}
			if (Object.prototype.toString.call(options.value) == '[object Array]') {
				options.value = JSON.stringify(options.value);
			}
			localStorage.setItem(options.key, options.value);
		}
	}
	//拿到缓存
	getItem(key) {
		let item = localStorage.getItem(key);
		if (item != null) {
			//先将拿到的试着进行json转为对象的形式
			try {
				item = JSON.parse(item);
			} catch (error) {
				//如果不行就不是json的字符串,就直接返回
				item = item;
			}
			//如果有startTime的值,说明设置了失效时间
			if (item.startTime != null) {
				let date = new Date().getTime();
				//何时将值取出减去刚存入的时间,与item.expires比较,如果大于就是过期了,如果小于或等于就还没过期
				if (date - item.startTime > item.expires) {
					//缓存过期,清除缓存,返回false
					localStorage.removeItem(key);
					return false;
				} else {
					//缓存未过期,返回值
					return item.value;
				}
			} else {
				//如果没有设置失效时间,直接返回值
				return item;
			}
		} else {
			return null;
		}
	}
	//移出缓存
	removeItem(key) {
		localStorage.removeItem(key);
	}
	//移出全部缓存
	clear() {
		localStorage.clear();
	}
}

使用

保存:

保存:参数可以设置三个,name-作为键key,value-作为值value,expires-过期时间(毫秒)

let storage = new Storage();
storage.setItem({//保存(过期时间没有默认值,不设置则不会过期)
        key:"name",
       	value:"小黑"
    })

获取:

let value = storage.getItem('name');//获取
console.log('大家好,我是',value);

扩展

localStorage有大小的限制(通常在 2.5-10M之间),有大数据量存储需求可以使用插件localForage

localForage使得离线数据存储在任何浏览器都是一项容易的任务。若浏览器不支持 IndexedDB 或 WebSQL,则使用 localStorage。localForage 的使用方法与localStorage相似很容易上手,可以查看官方文档了解。

默认情况下,localForage 按照以下顺序选择数据仓库的后端驱动:

  1. IndexedDB
  2. WebSQL
  3. localStorage

注意:vue-cli开发的项目中使用,可以查看这篇文档

应用场景:移动APP开发,数据保存在本地,无大小限制。(表数据也可以使用json格式保存)



前端数据库

前端数据库——WebSQLIndexedDB

IndexedDB API是强大的,但对于简单的情况可能看起来太复杂。如果你更喜欢一个简单的API,请尝试 localForagedexie.jsPouchDBidbidb-keyvalJsStore 或者 lovefield 之类的库,这些库使 IndexedDB 对开发者来说更加友好。

注意:Web SQL兼容性不好,一般使用基于IndexedDB API的第三方库来简化数据存储操作。


案例

WebSQL案例,了解学习即可,Web SQL的兼容性并不是特别理想,仅chrome ,safari,opera 10.5+等浏览器支持。

封装DaoTools工具

封装DaoTools工具(一个json对象),可以保存在单独的js文件中,通过script标签引入使用。

根据需要创建数据库,编写相应的crud函数,也可以直接调用transaction函数使用sql语句进行crud操作。

//前端数据库Web SQL,Web SQL的兼容性并不是特别理想,仅chrome ,safari,opera 10.5+等浏览器支持。
//注意:数据库操作是异步的,需要采用回调函数的方式操作数据库
DaoTools = {
	//数据库操作对象
	db: null,
	//初始化数据库对象
	init: function() {
		if (typeof openDatabase == 'undefined') {
			alert('当前浏览器不支持Web SQL,建议使用Chrome浏览器!');
			return;
		}
		//参数分别为:数据库名称、版本号、描述文本、数据库大小、创建回调
		//若不存在则创建
		this.db = openDatabase('myDB', '1.0', '前端数据库,Web SQL', 1024 * 1024 * 10);
		//transaction 数据库的事务函数(在其中使用executeSql函数执行sql。有一个executeSql执行失败都会回滚)
		this.db.transaction(function(tx) {
			//executeSql函数:
			// 第一个参数为sql语句;第二个参数为sql语句中占位符?对应的数据(数组);第三、四个参数为成功和失败时的回调函数

			//若不存在表userinfo则创建。列名 username,数据类型 TEXT;列名 password,数据类型 TEXT;。。。
			tx.executeSql(
				'CREATE TABLE IF NOT EXISTS userinfo(username TEXT,password TEXT, email TEXT)', []);
			//创建系统变量表(保存键值对key/value)
			tx.executeSql('CREATE TABLE IF NOT EXISTS sysparam(key TEXT,value TEXT)', []);
			//往userinfo表中插入一条数据
			DaoTools.addUser({
				username: 'admin',
				password: '12345',
				email: '1135637451@qq.com'
			});
		});
	},
	//预留transaction接口,用于执行sql。通过DaoTools.transaction()调用
	transaction: function(backCall) {
		DaoTools.db.transaction(backCall);
	},

	/**
	 * 执行sql,增删改查
	 * @param {string} sql sql语句
	 * @param {string[]} params ?占位符对应的数据,数组
	 * @param {requestCallback} hdcall sql执行成功后的回调
	 */
	update: function(sql, params, hdcall) {
		DaoTools.db.transaction(function(tx) {
			tx.executeSql(sql, params,
				function(tx, rs) {
					console.log('sql执行成功!');
					if (hdcall) hdcall();
				},
				function(tx, error) {
					console.error('sql执行失败!\r\n' + error.source + "::" + error.message);
				}
			);
		});
	},

	/**
	 * 获取用户信息
	 * @param {string} username 用户名(账号)
	 * @param {requestCallback} backCall 回调(接收数据)
	 * @return {Object} 用户信息
	 */
	getUserinfo: function(username, backCall) {
		DaoTools.db.transaction(function(tx) {
			//执行查询
			tx.executeSql('SELECT * FROM userinfo WHERE username = ?', [username],
				function(tx, rs) {
					var json = {};
					if (rs.rows.length > 0) {
						json = rs.rows.item(0);
					}
					backCall(json);
				},
				function(tx, error) {
					console.error(error.source + "::" + error.message);
				}
			);
		});
	},

	/**
	 * 新增用户
	 * @param {Object} userData 用户名username、密码password为必填项
	 * @param {requestCallback} backCall 回调
	 * @return {string} errMsg 若用户信息不完整,则会返回错误信息
	 */
	addUser: function(userData, backCall) {
		var errMsg = '';
		//用户名、密码必填
		if (!userData || !userData.username || !userData.password) {
			errMsg = '请完善用户信息!';
			if (backCall) backCall(errMsg);
			return;
		}
		//先查询,用户名不能相同
		DaoTools.getUserinfo(userData.username, data => {
			if (Object.keys(data).length > 0) {
				errMsg = '存在同名用户!';
				if (backCall) backCall(errMsg);
				return;
			}
			DaoTools.db.transaction(function(tx) {
				//新增数据
				tx.executeSql(
					'INSERT INTO userinfo(username,password,email) VALUES(?,?,?)',
					[userData.username, userData.password, userData.email ? userData.email :
						''
					],
					function(tx, rs) {
						console.log(`新增用户${userData.username}成功`);
						if (backCall) backCall();
					},
					function(tx, error) {
						console.error(error.source + "::" + error.message);
					}
				);
			});
		});
	},

	//获取系统常用变量
	getParam: function(key, backCall) {
		DaoTools.db.transaction(function(tx) {
			//执行查询
			tx.executeSql('SELECT * FROM sysparam WHERE key = ?', [key],
				function(tx, rs) {
					var v = '';
					if (rs.rows.length > 0) {
						v = rs.rows.item(0).value;
					}
					backCall(v);
				},
				function(tx, error) {
					console.error(error.source + "::" + error.message);
				}
			);
		});
	},

	//保存系统常用变量
	setParam: function(key, value, backCall) {
		DaoTools.db.transaction(function(tx) {
			//先删除再新增
			tx.executeSql('DELETE FROM sysparam WHERE key = ?', [key]);
			//新增数据
			tx.executeSql('INSERT INTO sysparam(value, key) VALUES(?, ?)', [value, key],
				function(tx, rs) {
					if (backCall) backCall();
					console.log(key + "::" + value)
				},
				function(tx, error) {
					console.error(error.source + "::" + error.message);
				}
			);
		});
	},

	/**
	 * 查询所有数据
	 * @param {string} tableName 表名
	 * @param {requestCallback} backCall 回调(接收数据)
	 * @return {Object[]} 数组
	 */
	queryAll: function(tableName, backCall) {
		DaoTools.db.transaction(function(tx) {
			tx.executeSql(`select * from ${tableName}`, [],
				function(tx, rs) {
					var json = [];
					for (var i = 0; i < rs.rows.length; i++) {
						json[i] = rs.rows.item(i);
					}
					backCall(json);
				},
				function(tx, error) {
					console.error(error.source + "::" + error.message);
				}
			);
		});
	},

	/**
	 * 通用查询数据,支持分页
	 * @param {string} sql sql语句
	 * @param {string[]} params ?占位符对应的数据,数组
	 * @param {requestCallback} backCall 回调(接收数据)
	 * @param {string} pageSize 页面大小(一页的数据量)
	 * @param {string} pageIndex 页码(从1开始)
	 * @return {Object[]} 数组
	 */
	query: function(sql, params, backCall, pageSize, pageIndex) {
		DaoTools.db.transaction(function(tx) {
			//传入的页序号是从1开始的,需要-1
			if (pageSize && pageIndex) {
				sql = sql + ' limit ' + pageSize + ' offset ' + pageSize * (pageIndex - 1);
				pageIndex = pageIndex - 1;
			}
			console.log(`sql = ${sql}`);

			if (!params) params = [];

			tx.executeSql(sql, params,
				function(tx, rs) {
					var json = [];
					for (var i = 0; i < rs.rows.length; i++) {
						json[i] = rs.rows.item(i);
					}
					backCall(json);
				},
				function(tx, error) {
					console.error(error.source + "::" + error.message);
				}
			);
		});
	},

	/**
	 * 清除数据库信息,初始化
	 */
	clear: function() {
		var me = this,
			cnt = 0;
		var cb = function() { //重新创建表对象
			cnt++;
			if (cnt == 2) { //确保两张表都删掉了,再初始化
				me.init();
				alert('初始化成功!');
			}
		};

		this.db.transaction(function(tx) {
			tx.executeSql('DROP TABLE userinfo', [], cb);
			tx.executeSql('DROP TABLE sysparam', [], cb);
		});
	},
};

//初始化(匿名函数,立即执行)
//script标签引入该js文件后,就会初始化数据库
(function() {
	DaoTools.init();
})();

使用

DaoTools是一个json对象,直接DaoTools.queryAll方式调用其中封装的函数即可。

DaoTools.queryAll('userinfo',data=>{
	console.log(`userinfo表的数据 = \r\n ${JSON.stringify(data)}`);
	// userinfo表的数据 = 
	//  [{"username":"admin","password":"12345","email":"1135637451@qq.com"}]
})

DaoTools.getUserinfo('admin',data=>{
	console.log(`用户admin的信息 = \r\n ${JSON.stringify(data)}`);
	// 用户admin的信息 = 
	//  {"username":"admin","password":"12345","email":"1135637451@qq.com"}
})

扩展

Web SQL的兼容性并不是特别理想,归咎其原因,主要是因为 Web SQL Database API 实际上并不包含在 HTML5 规范之中。它是一个独立的规范,它引入了一套使用 SQL 操作客户端数据库的 API。其规范已经被停止更新了,所以大多数浏览器并不支持。
Web SQL相对于 sessionStorage ,locationStorage最大的**优势 :**能方便的进行对象存储、能进行大量的数据的处理。


总结

  • 主要用于PC端的web 应用,想使用sql语句进行数据crud操作,可以使用Web SQL
  • 页面传递参数、状态记录等小数据量场景,可以考虑Storage API
  • 不是上边的应用场景,建议使用插件localForage

原文链接:前端数据存储

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值