190  
查询码:00001167
uni-app缓存器的封装
来源:https://blog.csdn.net/weixin_33887443/article/details/93178902
作者: 朱凡 于 2020年03月15日 发布在分类 / FM组 / FM_App 下,并于 2020年03月15日 编辑
阅读 阅读数 读数 缓存 uni-app 数据 博客 来自 程序 uniapp

uni-app缓存器的封装

地址:https://gitee.com/zhufan/min-cache

下面是基本代码,会在此基础上进行增强

class MinCache {
 // 将数据存储在本地缓存中指定的 name 中 set (name, data) {
  try {
   uni.setStorageSync(name, data)
  } catch (e) {
   console.log(e)
  }
 }
 // 从本地缓存中获取指定 name 对应的内容
 get (name) { let data
  try {
   data = uni.getStorageSync(name)
  } catch (e) {
   console.log(e)
  } return data
 }
 // 从本地缓存中移除指定 key
 delete (name) {
  try {
   uni.removeStorageSync(name)
  } catch (e) {
   console.log(e)
  }
 }
 // 返回一个布尔值,表示 name 是否在本地缓存之中
 has (name) {
  const value
  try {
   const res = uni.getStorageInfoSync()
   value = res.keys.includes(name)
  } catch (e) {
   console.log(e)
  } return value
 }
 // 清理本地数据缓存 clear () {
  try {
   uni.clearStorageSync()
  } catch (e) {
   console.log(e)
  }
 }
} export default MinCache复制代码

我们知道缓存往往是有危害的,那么我们最好规定个时间来去除数据。

class CacheCell {
 constructor (data, timeout) {
  this.data = data
  // 设置超时时间,单位秒
  this.timeout = timeout
  // 对象创建时候的时间
  this.createTime = Date.now()
 }
}复制代码
set (name, data, timeout = 1200) {
  const cachecell = new CacheCell(data, timeout)
  try {
   uni.setStorageSync(name, cachecell)
  } catch (e) {
   console.log(e)
  }
 }
 get (name) { let data = null
  try {
   data = uni.getStorageSync(name) if (!data) return null
   const currentTime = Date.now()
   const overTime = (currentTime - data.createTime) / 1000 if (overTime > data.timeout) {
    try {
     uni.removeStorageSync(name)
     data = null
    } catch (e) {
     console.log(e)
    }
   }
  } catch (e) {
   console.log(e)
  } return data
 }复制代码

使用了过期时间进行缓存的方式,已经可以满足绝大部分的业务场景。

uni-app的Storage在不同端的实现不同:

  • H5端为localStorage,浏览器限制5M大小,是缓存概念,可能会被清理

  • App端为原生的plus.storage,无大小限制,不是缓存,持久化

  • 各个小程序端为其自带的storage api,数据存储生命周期跟小程序本身一致,即除用户主动删除或超过一定时间被自动清理,否则数据都一直可用。

  • 微信小程序单个 key 允许存储的最大数据长度为 1MB,所有数据存储上限为 10MB。

  • 支付宝小程序单条数据转换成字符串后,字符串长度最大200*1024。同一个支付宝用户,同一个小程序缓存总上限为10MB。

  • 百度、头条小程序文档未说明大小限制

除此之外,H5端还支持websql、indexedDB、sessionStorage;App端还支持SQLite、IO文件等本地存储方案。

我们可以看出来Storage在一些端中是有大小限制的,其实我们的数据只是想要缓存,不一定要持久化。

也就是说在应用程序生命周期内使用就行,而且直接操作Storage也不是很好。

我们知道ES6中有Map可以做缓存

下面代码时基于Map封装的

let cacheMap = new Map() let instance = null let timeoutDefault = 1200 function isTimeout (name) {
 const data = cacheMap.get(name) if (!data) return true if (data.timeout === 0) return false const currentTime = Date.now()
 const overTime = (currentTime - data.createTime) / 1000 if (overTime > data.timeout) {
  cacheMap.delete(name) return true } return false }

class CacheCell {
 constructor (data, timeout) {
  this.data = data
  this.timeout = timeout
  this.createTime = Date.now()
 }
}

class Cache { set (name, data, timeout = timeoutDefault) {
  const cachecell = new CacheCell(data, timeout) return cacheMap.set(name, cachecell)
 }
 get (name) { return isTimeout(name) ? null : cacheMap.get(name).data
 }
 delete (name) { return cacheMap.delete(name)
 }
 has (name) { return !isTimeout(name)
 } clear () { return cacheMap.clear()
 } setTimeoutDefault (num) { if (timeoutDefault === 1200) { return timeoutDefault = num
  }
  throw Error('缓存器只能设置一次默认过期时间')
 }
}

class ProxyCache { constructor () { return instance || (instance = new Cache())
 }
} export default ProxyCache复制代码

对Storage和Map封装的缓存进行整合

我们来分析一下

  • Storage和Map共用一套api

    • 在命名上解决以下划线_开头命名的缓存到Storage,并且Map也有副本

  • 尽量不操作Storage(读取速度慢)

    • 那就必须在应用程序初始化的时候把Storage加载进Map

  • 像Vue插件一样使用

let cacheMap = new Map() let timeoutDefault = 1200 function isTimeout (name) {
 const data = cacheMap.get(name) if (!data) return true if (data.timeout === 0) return false const currentTime = Date.now()
 const overTime = (currentTime - data.createTime) / 1000 if (overTime > data.timeout) {
  cacheMap.delete(name) if (name.startsWith('_')) {
   try {
    uni.removeStorageSync(name)
   } catch (e) {
    console.log(e)
   }
  } return true } return false }

class CacheCell {
 constructor (data, timeout) {
  this.data = data
  this.timeout = timeout
  this.createTime = Date.now()
 }
}

class MinCache {
 constructor (timeout) {
  try {
   const res = uni.getStorageInfoSync()
   res.keys.forEach(name => {
    try {
     const value = uni.getStorageSync(name)
     cacheMap.set(name, value)
    } catch (e) {
     console.log(e)
    }
   })
  } catch (e) {
   console.log(e)
  }
  timeoutDefault = timeout
 } set (name, data, timeout = timeoutDefault) {
  const cachecell = new CacheCell(data, timeout) let cache = null if (name.startsWith('_')) {
   try {
    uni.setStorageSync(name, cachecell)
    cache = cacheMap.set(name, cachecell)
   } catch (e) {
    console.log(e)
   }
  } else {
   cache = cacheMap.set(name, cachecell)
  } return cache
 }
 get (name) { return isTimeout(name) ? null : cacheMap.get(name).data
 }
 delete (name) { let value = false if (name.startsWith('_')) {
   try {
    uni.removeStorageSync(name)
    value = cacheMap.delete(name)
   } catch (e) {
    console.log(e)
   }
  } else {
   value = cacheMap.delete(name)
  } return value
 }
 has (name) { return !isTimeout(name)
 } clear () { let value = false try {
   uni.clearStorageSync()
   cacheMap.clear()
   value = true } catch (e) {
   console.log(e)
  } return value
 }
}

MinCache.install = function (Vue, {timeout = 1200} = {}) {
 Vue.prototype.$cache = new MinCache(timeout)
} export default MinCache复制代码

使用方法

name以下划线_开头命名的缓存到Storage,并且Map也有副本

事件名 参数 说明 返回值
set name缓存的key,data缓存的数据,timeout(必须数字单位s)缓存时间,默认缓存1200s, timeout设置为0表示永久缓存 设置缓存数据 Map集合
get name缓存的key 获取数据(缓存过期将返回null) 返回缓存的数据data
has name缓存的key 检查值 true/false
delete name缓存的key 删除数据 true/false
clear - 清空Storage和Map缓存数据 true/false
// 注册缓存器
Vue.use(MinCache)
// 设置默认缓存时间
// Vue.use(MinCache, {timeout: 600})复制代码
// 'name'不是以下划线开头的表示会缓存到Map中,在程序生命周期内有并且在有效时间内有效
this.$cache.set('name', 'MinCache')

// 过期时间设置为0表示不会过期
// 注意:'test'并不是以下划线命名表示在程序生命周期永久缓存
this.$cache.set('test', 'testdemo', 0)

// 过期时间设置为0表示不会过期
// 注意:'_imgURL'是以下划线命名表示永久缓存到Storage
this.$cache.set('_imgURL', 'data', 0)复制代码
// 获取缓存的数据
this.imgURL = this.$cache.get('_imgURL')
this.name = this.$cache.get('name')
this.test = this.$cache.get('test')复制代码


 推荐知识

 历史版本

修改日期 修改人 备注
2020-03-15 19:34:06[当前版本] 朱凡 格式调整
2020-03-15 19:26:57 朱凡 格式调整
2020-03-15 19:26:44 朱凡 创建版本

  目录
    知识分享平台 -V 4.8.7 -wcp