uni-app缓存器的封装

在前端开发应用程序中,性能一直都是被你们所重视的一点,然而判断一个应用程序的性能最直观的就是看页面打开的速度。其中提升页页面反应速度的一个方式就是使用缓存。一个优秀的缓存策略能够缩短页面请求资源的距离,减小延迟,而且因为缓存文件能够重复利用,还能够减小带宽,下降网络负荷。html

前端经常使用缓存技术在这里我就再也不描述,下面基于Storage对其进行加强,采用Map 基本相同的api。前端

阅读如下内容时遇到不懂的,请先科普阮一峰老师的ECMAScript 6 入门html5

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

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
  }复制代码

使用了过时时间进行缓存的方式,已经能够知足绝大部分的业务场景。git

uni-app的Storage在不一样端的实现不一样:es6

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

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

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

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

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

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

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

咱们能够看出来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')复制代码

具体使用方法能够参考github

uni-app路由的封装

相关文章
相关标签/搜索