当前位置: 首页 > ai >正文

uniapp运行在app端如何使用缓存

uniapp运行在app端如何使用缓存

​ 众所周知,uniapp可以一套代码,多端运行。但是需要注意的是,window对象以及document是浏览器特有的(所以app端无法使用localStorage等api),因此,uniapp贴心的为我们准备了getStorage以及setStorage等操作缓存的api。除此以外,还有vue官方推荐的pinia也可以操作缓存。那么当这两者同时存在于一个项目时,我们应该是他们完美结合起来呢?

为什么uniapp提供了所需的api之后还要用到pinia呢?

​ 有这么一个场景:在程序启动时我需要轮询服务器接口获取是否新数据的产生,如果有,则将hasRead字段设为true,又因为这个hasRead字段我需要在程序启动时就能拿到值,因此我是用setStorageapi将其写进缓存。那么,问题来了,我如何将缓存的字段变为响应式的呢?为什么需要响应式?因为当有新数据产生时,我需要在界面中提示用户,而这个字段我是设置在缓存当中的。最开始我是用了以下2种方式来达到响应式的结果。

// 第一种
const cache = uni.getStorageSync('hasRead')
const hasRead = ref(cache)watch(() => hasRead.value, (newval) => {if (newval) {hasRead.value = newval}
})// 第二种
const hasRead = ref(true)
const hasReadCache = computed(() => {const cache = uni.getStorageSync('hasRead')if (cache) {return cache}return hasRead.value
})

答案显而易见,以上2种方案都无法使缓存变化的同时响应到页面当中(有小伙伴知道原因的话,评论区留言告诉我一下为什么不可以),于是,我秉着试一试的想法使用了pinia以及pinia-plugin-persistedstate

import { defineStore } from 'pinia'
import { ref } from 'vue'
export const useSettingStore = defineStore('setting', () => {const hasRead = ref(true)const setHasRead = (value) => {hasRead.value = value}
}, {persist: {storage: localStorage,pick: ['hasRead']}
})

通过pinia,我成功实现的数据的响应式,并且能够将数据存于缓存。那么,问题解决了吗?并没有。为什么呢?因为程序最终时需要运行在Android以及IOS环境的,而以上环境并没有window对象,因此也不会有localStorage。那么应该怎么办呢?机缘巧合之下,当我鼠标移入persist钟的storage对象时,编辑器跳出来他的类型为StorageLike,直译一下就是像Storage,那么是不是可以理解为我声明一个Storage对象,只要具有像localStorage对象的api也可以呢?刚好uniapp也提供了类似的api,说干就干,我创建了一个类,如下:

// utils/storage.jsclass Storage {/*** 设置缓存* @param {string} key 缓存键* @param {any} value 缓存值* @param {number} [expire] 过期时间(单位:秒)* @returns {boolean} 是否设置成功*/setItem(key, value, expire) {try {const data = {value,// 计算过期时间戳(如果设置了过期时间)expireTime: expire ? Date.now() + expire * 1000 : null,};uni.setStorageSync(key, data);return true;} catch (e) {console.error('Storage setItem error:', e);return false;}}/*** 获取缓存(自动处理过期数据)* @param {string} key 缓存键* @returns {any|null} 缓存值或null*/getItem(key) {try {const data = uni.getStorageSync(key);if (!data) return null;// 检查是否过期if (data.expireTime && Date.now() > data.expireTime) {this.removeItem(key);return null;}return data.value;} catch (e) {console.error('Storage getItem error:', e);return null;}}/*** 删除指定缓存* @param {string} key 缓存键*/removeItem(key) {try {uni.removeStorageSync(key);} catch (e) {console.error('Storage removeItem error:', e);}}/*** 清空所有缓存*/clear() {try {uni.clearStorageSync();} catch (e) {console.error('Storage clear error:', e);}}/*** 检查缓存是否存在* @param {string} key 缓存键* @returns {boolean}*/has(key) {return this.keys().includes(key);}/*** 获取所有缓存键* @returns {string[]}*/keys() {try {const { keys } = uni.getStorageInfoSync();return keys;} catch (e) {console.error('Storage keys error:', e);return [];}}/*** 获取缓存信息* @returns {{*   keys: string[],*   currentSize: number,*   limitSize: number* }}*/getInfo() {try {return uni.getStorageInfoSync();} catch (e) {console.error('Storage getInfo error:', e);return { keys: [], currentSize: 0, limitSize: 0 };}}/*** 设置缓存过期时间* @param {string} key 缓存键* @param {number} expire 过期时间(单位:秒)* @returns {boolean}*/setExpire(key, expire) {const value = this.getItem(key);if (value === null) return false;return this.setItem(key, value, expire);}/*** 检查并清理所有过期缓存*/checkExpire() {this.keys().forEach((key) => {// 通过getItem自动触发过期检查this.getItem(key);});}
}// 创建单例实例
export const storage = new Storage();

利用storage对象,我将store变成以下代码:

import { defineStore } from 'pinia'
import { ref } from 'vue'
import { storage } from '@utils'
export const useSettingStore = defineStore('setting', () => {const hasRead = ref(true)const setHasRead = (value) => {hasRead.value = value}
}, {persist: {storage: {getItem: (key) => storage.getItem(key),setItem: (key, value) => storage.setItem(key, value),removeItem: (key) => storage.removeItem(key),},pick: ['hasRead']}
})

通过以上思路,我成功解决了uniapp的storagepinia的结合,并解决了缓存的响应式问题。

最后,虽然这个轮询的方案被我废弃了,但是我还是从其中学到了之前我从未接触到的东西。还有就是如果小伙伴学到了的话,也请点赞,关注。感谢您的支持!!

http://www.xdnf.cn/news/91.html

相关文章:

  • 【ubuntu】在Linux Yocto的基础上去适配Ubuntu的wifi模块
  • 科技如何改变世界?
  • 微博辐射源和干扰机
  • Hadoop的三大结构及其作用
  • leetcode 309. Best Time to Buy and Sell Stock with Cooldown
  • 热门与冷门并存,25西电—电子工程学院(考研录取情况)
  • 如何在米尔-STM32MP257开发板上部署环境监测系统
  • Windows 图形显示驱动开发-WDDM 1.2功能—Windows 8 中的 DirectX 功能改进(五)
  • 什么是单元测试的“覆盖率”
  • 计算机视觉——基于使用 OpenCV 与 Python 实现相机标定畸变校正
  • 安全测试报告模板
  • PyTorch 浮点数精度全景:从 float16/bfloat16 到 float64 及混合精度实战
  • pnpm解决幽灵依赖问题
  • [Unity]-[UI]-[Prefab] 关于UGUI UI Prefab的制作技巧
  • C++: 类和对象(中)
  • 避免IP地址关联,多个手机设备的完美公网IP问题
  • Django ORM 定义模型
  • 【html】a标签target属性以及扩展应用
  • 2025TGCTF Web WP复现
  • 2025年03月中国电子学会青少年软件编程(Python)等级考试试卷(六级)答案 + 解析
  • 多线程编程的简单案例——单例模式[多线程编程篇(3)]
  • 前端零基础入门到上班:Day7——表单系统实战全解析
  • 文献总结:NIPS2023——车路协同自动驾驶感知中的时间对齐(FFNet)
  • node.js 基础
  • 9.Rust+Axum 测试驱动开发与性能优化全攻略
  • 韩媒专访CertiK创始人顾荣辉:黑客攻击激增300%,安全优先的破局之路
  • 在Vmware15(虚拟机免费) 中安装纯净win10详细过程
  • Google Gemini 系列AI模型 的详细解析,涵盖其技术特点、版本差异、应用场景及优势
  • 网络417 路由转发2 防火墙
  • 2025第十七届“华中杯”大学生数学建模挑战赛题目B 题 校园共享单车的调度与维护问题完整成品正文33页(不含附录)文章思路 模型 代码 结果分享