Skip to content

25 客户端存储

写在前面 :IndexedD 索引暂时没有学习整理

cookies

限制
  • cookies 与特定的域绑定 这个限制保证了 只能被认可的接受者接受 不可以被其他域访问
  • 不要超过300个cookie
  • 每个域的cookie总数不超过20个
  • 每个cookie不能超过4096字节
  • 每个域不能超过81920字节 🚶 不同浏览器存在差异 例如:
  • 最新的IE 与 Edge 限制每个域不超过 50个cookie
  • 最新的fireFox 限制每个域不超过 150个cookie
  • 最新的Opera 限制每个域不超过 180个cookie
  • Safari 和 Chrome 对每个域的cookie数没有限制 🖕 如果cookie 总数超过单个域 上限 浏览器会删除之前设置的cookie。浏览器之间会存在差异,避免不确定性,不要超出限制。
cookies的构成
  • 名称: 唯一标识cookie 的名称,不区分大小写;
  • 值: 存储 字符串值,值必须经过URL 编码。
  • 过期时间: 何时删除cookie值 ;时间到了立即删除 未设置时间 会话结束删除 cookie
  • 安全标志: 设置之后 只使用SSL安全连接的情况下 才会把cookie 发送到服务器。例如请求 https:// xxx 会携带 cookie http:xx则不会携带
  • cookie 设置了secure 只能在SSL连接上发送
  • 通过 document.cookie 设置; 例如:document.cookie ="name=value"
  • 所有的值与名必须是URI编码; 必须使用decodeURIComponent() 解码;
  • 简化繁杂操作 可以使用cookie.js
子cookie
  • 一个键的值 对应多组键值关系的结构;例如:name=name1=value1&name2=value2&name3=value3;

  • 实际开发中注意不要超出单个cookie大小

使用cookie 的注意事项
  • HTTP-only 的cookie ;可以在服务器或浏览器进行设置;只能在服务器读取

  • cookie 存储大量的信息 可能会影响 浏览器的性能;保存cookie越大 请求耗费时间越长;

  • cookie不要存放敏感数据 不安全 任何人都可以获取

web Storage

规范中的两个目标

  • 提供在cookie 之外的存储会话数据途径
  • 提供跨会话持久化存储大量数据机制
  • 定义了两个对象:localStorage 和 sessionStorage
  • localStorage 是永久的存储机制;sessionStorage 是跨会话的存储机制
storage类型

增加了如下方法

  • clear():删除所有值;
  • getItem(name):获取name的值;
  • key(index):取得给定位置的名称;
  • removeItem(name):删除给定name的名值对;
  • setItem(name,value);设置给定name的value
sessionStorage 对象
  • 只存储会话数据,只能保存数据到浏览器(当前页面)关闭

  • 存储的sessionStorage 不受页面刷新的影响;

  • sessionStorage 对象 与服务器会话紧密相关 运行本地文件不能使用

  • 存储在sessionStorage对象的数据 只能在最初的页面使用 再多页面程序用处有限;

  • 添加数据 两种方式:

    • sessionStorage.setItem("name","value") //使用setItem实现
    • sessionStorage.name = value // 使用属性存储数据
  • 所有现代浏览器实现存储写入 都是使用同步阻塞方式,因此数据会立即提交到存储;

  • 获取属性 两种方式:

    • sessionStorage.getItem('name')//通过 getItem实现
    • sessionStorage.name //使用对象属性方式 获取
  • 遍历所有值可以通过 for循环与 key()方法实现

  • 删除属性

    • sessionStorage.removeItem(name) 实现
    • delete sessionStorage.name //对象方法实现
localStorage 对象

H5规范里localStorage对象取代了 globalStorage 作为浏览器持久化的存储数据的机制

想要访问同一个localStorage 对象 页面必须是同一个域(子域不可以)

  • localStorage 也是 storage 的实例 所以同样可以使用 Storage 上的方法

localStorage 与 sessionStorage 区别

  • localStorage 会保留数据 失效方式:只能用户主动清除缓存或通过JavaScript删除
  • localStorage 数据 不受 重启浏览器 关闭标签的的影响
存储事件
  • 每当 storage对象发生变化时就会触发 ‘storage’事件

  • 触发方式

    • 设置属性
    • 删除属性
    • 清除所有 数据clear()
  • 事件对象 有如下四个属性:

    • domain:存储变化对应的域
    • key:被设置或者删除的键
    • newVal:键被设置的的新值,若删除则为null
    • oldValue:键变化之前的值
  • 具体监听storage事件如下

    javascript
    window.addEventListener('storage',(event)=>{
        console.log(event.domain)
    })
  • storage 事件 不会对 sessionStorage 与 localStorage 对象作区分 任何一个改变都会触发

限制
  • 不同浏览器 给localStorage 和sessionStorage 设置了不同的空间限制
  • 大多数会限制每个源5MB

IndexedDB

  • IndexedDB 是现代浏览器中存储 数据化结构 的方案
  • IndexedDB 是为了代替目前废除的 WebSQL Database API。
  • 创建一套API 方便对象的存储与获取
  • IndexedDB 几乎是完全异步的
  • 绝大多数的IndexedDB 操作要求添加 onerror 和 onsuccess 事件处理程序 来确定输出
  • 数据库
    • 使用IndexedDB
      • 调用 indexedDB.open()方法 ,并传入名称,名称存在则打开;不存在则创建并打开;并返回一个IDBRequest实例
      • 实例上添加onsuccess 监听成功的回调函数
      • 实例上添加onerror 监听失败的回调
      • 可以通过event.target.result 得到当前的db对象
      • event.target.errrorCode 来存储出现问题的状态码
  • 对象存储
    • 数据库不存在 open会创建一个数据库 然后触发 upgradeneeded事件
    • 如果数据库存在 升级了版本号 也会触发upgradeneeded事件
    • 可以在事件处理程序中更新数据库模式
  • 事务
    • 事务是通过带哦用数据库的transaction方法创建。例如:let transaction=db.transaction()
    • transaction 不指定参数 数据库所有对象仅有只读权限
    • bd.transaction('xx') 参数可以是一个字符串 或者字符串型数组,实现访问一个或多个对象存储
    • 当 传入第二个参数 可以是**‘readonly’‘readwrite’‘versionchange’**;可读 、可写
    • 有了事务引用 可以使用 objectStore()方法,传入对象存储名称来实现访问特定存储对象
    • 可以使用 add put 添加或修改对象 ,get获取对象,delete删除,clear清除所有对象
    • 事务的事件处理 onerroroncompute
    • 不可以在 oncompute中访问 get()请求返回的任何数据 仍需通过onsuccess 获取数据
  • 插入对象
    • add
    • 事件变化都会触发 onsuccess onerror 其中一个事件
  • 通过游标查询
    • 可以实现获取多条数据
    • 游标是 指向结果集的指针 ,与传统数据库查询方式不同 游标指向第一个结果后 并在接受指令前 不会主动查找下一条数据
    • 需要在对象上 调用 openCursor()方法创建游标,同样创建完成会返回一个request 可以监听其onsuccess 和onerror 事件
    • 此时request 保存的是*IDBCursor** 的实例,包含几个属性
      • direction:字符串常量,表示游标的前进方向以及是否应该遍历所有重复的值。可能包括 next,nextunique,prev,prevunique;
      • key:对象的键
      • value:对象的值
      • primaryKey:游标使用的键,可能是对象键或引用键
    • 更新记录 update方法使用指定的游标对象更新当前指向的对象的值,同时会返回一个request对象 可以通过 onerror 和onsuccess 监听 结果
    • 删除记录 delete方法来实现删除游标位置的记录,与update 类似
    • 值得注意的是 当事务没有 删除与修改的权限时 会抛出错误
    • 前面提到 默认情况下 游标只会创建一个请求 要创建下一次请求 必须调用以下方法
      • continue(key):移动结果集的下一条记录 参数key可选的 无走向下一条,有则游标指向指定的键;
      • advance(count):游标详情移动指定的count条记录
  • 键范围
    • 键范围 对应IDBkeyRange 的实例。
    • 有四种方式指定键范围
      • only(key) ;类似与直接访问对象存储并调用get(key);
      • 定义结果集下限 ,下限表示游标开始的位置
        • IDBRange.lowerBound(key,bool) //参数一key,参数二:true表示从key之后开始,false or 不传表示从key到结束
      • 定义结果集上限 上限表示从头开始到key结束 第二个参数传递true不包含 key
        • IDBRange.uppperBound(key,bool)
      • 同时设定上下限 通过bound 来实现
        • 参数1上限 ,参数2下限参,数3是否包含上限内容,参数4是否包含下限
        • 例如 IDBRange.bound('007','ace',fasle,true) // ['007','ace')
    • 定义完键范围 传给openCursor()方法就可以得到该范围的游标
  • 设置游标方向
    • openCursor 方法 实际上接受两个参数 ,参数1:IDBRange的实例,参数2 表示方向的字符串 默认方向是’next‘
    • nextunique 游标跳过重复项
    • 参数1 为null时,表示默认的额所有值
  • 索引
    • 🗡️ 暂时省略
  • 并发问题
    • 产生场景 不同浏览器标签打开同一个网页 可能一个尝试升级 另一个尚未就绪
    • 解决办法
      • 在第一次打开数据库时添加 onversionchange
      • 同源标签将数据库打开时 将会执行回调 执行立即关闭数据库 以便完成数据库版本的升级
      • 监听 同步处理
  • 限制
    • IndexedDB 数据库 是与页面源(协议、域名和端口)绑定的,信息不可以跨域
    • 存储扣减每个源 都有自己独立的存储空间 firefox 限制 每个源50MB 移动端5MB chrome 时5MB超出配额则请求用户许可;
    • firefox 还有个限制 本地文件不能访问IndexedDB 数据库??。Chrome 没有限制
  • 小结
    • 数据没有加密,不适合存储安全数据