关于javascript:项目实战之本地存储篇

在前端我的项目开发中,前端的本地存储是必不可少的,明天小编就前端的本地存储在我的项目中的应用具体的介绍一下。前端本地存储次要有:

  • 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 < arrCookie.length; 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 //大于111
WHERE 列名称 GLOB >= 111 //大于等于111
WHERE 列名称 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/136…

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理