Vue3项目框架搭建封装,一次学习,终身受益【万字长文,满满干货】(三)

简介: Vue3项目框架搭建封装,一次学习,终身受益【万字长文,满满干货】

Pinia数据持久化插件

使用场景

把数据缓存下来,可以避免页面刷新时,重复调用接口,提升用户体验

封装sessionStorage localStorage

代码在 src/common/utils/storage.ts

let hasSessionStorage = true
let hasLocalStorage = true
//判断当前浏览器是否支持sessionStorage
if (sessionStorage) {
  try {
    sessionStorage.setItem('_sessionStorageTest', 'Hello World!')
    sessionStorage.removeItem('_sessionStorageTest')
  } catch (e) {
    hasSessionStorage = false
  }
} else {
  hasSessionStorage = false
}
//判断当前浏览器是否支持localStorage
if (localStorage) {
  try {
    localStorage.setItem('_localStorageTest', 'Hello World!')
    localStorage.removeItem('_localStorageTest')
  } catch (e) {
    hasLocalStorage = false
  }
} else {
  hasLocalStorage = false
}
/**
 * 设置本地缓存
 * @param key
 * @param val
 */
export function setLocalStorage(key: string, val?: any): void {
  if (!hasLocalStorage) {
    return
  }
  localStorage.setItem(key, JSON.stringify(val))
}
/**
 * 设置会话级别缓存
 * @param key
 * @param val
 */
export function setSessionStorage(key: string, val: any): void {
  if (!hasSessionStorage) {
    return
  }
  sessionStorage.setItem(key, JSON.stringify(val))
}

代码实现

核心就是,Pinia的监听API subscribe

state中的数据变化时,就会触发subscribe

这样我们就可以判断当前变化的store的id,是否在我们的需要持久化的数组中

如果在,我们就将数据存到本地缓存

const getStorageTypeMap: AnyObj = {
  sessionStorage: getSessionStorage,
  localStorage: getLocalStorage
}
const setStorageTypeMap: AnyObj = {
  sessionStorage: setSessionStorage,
  localStorage: setLocalStorage
}
const plugin = (options: Options): any => {
  // key 为标识前缀,避免命名空间冲突
  const { key, storeList } = options
  return (context: PiniaPluginContext) => {
    const { store } = context
    let storageType:any
    let obj: any = {}
    for (const item of storeList) {
      if (item.storeName.includes(store.$id)) {
         // storeName 为哪个store,path 为store下某个字段
        const { storeName, path } = item
        storageType = item.storageType
        // 如果key 不存在默认走 pinia
        const data = getStorageTypeMap[storageType](`${key ?? 'pinia'}-${store.$id}`)
        if (data) {
          // 更新store
          store.$patch(data)
        }
        if (path && path.length > 0) {
          // 如果存在path 则需要判断
          if (storeName.length === 1) {
            path.forEach((item) => {
              obj[item] = store.$state[item]
            })
          } else {
            return new Error('配置path 时只允许配置一个storeName')
          }
        }
        obj = path && path.length > 0 ? obj : store.$state
        storeName.includes(store.$id) &&
        store.$subscribe(() => {
          setStorageTypeMap[storageType](`${key ?? 'pinia'}-${store.$id}`, toRaw(obj))
        })
      }
    }
  }
}

全局引入

这个是我定义的store文件,里面定义了三个store,分别为main,test,test1

// piniaStore.js
import { defineStore } from 'pinia'
export const main = defineStore('main', {
  state: () => {
    return {
      test: 'hello word',
      test1: 'hello word1',
      configInfo: {}
    }
  },
  getters: {},
  actions: {}
})
export const test = defineStore('test', {
  state: () => {
    return {
      age: 18,
      name: 'yz'
    }
  }
})
export const test1 = defineStore('test1', {
  state: () => {
    return {
      age: 18,
      name: 'yz'
    }
  }
})

在入口文件处 引入插件,然后对进行需要存储的store和字段进行配置

  • key 为这个项目使用的一个命名前缀,保证不会污染到其他缓存数据
  • storeName 为一个数组,可以为空,默认存储所有store,可以配置自己需要存储的store名字
  • storageType 为字符串,可以配置需要会话级存储还是本地化存储
  • path 为一个数组,可以为空,默认存储该store下所有字段,可以配置自己需要的字段
import { createPinia } from 'pinia'
import piniaPlugin from '@/common/utils/piniaPlugin'
// 创建pinia 实例
const pinia = createPinia()
pinia.use(
  piniaPlugin({
    key: 'XXX', // 这是给缓存到本地时,加一个特殊的前缀,以免造成污染到其他缓存数据
    storeList: [
      {
        storeName: ['main'], // 对于特定store进行持久化,空或者不传,则对所有的store进行缓存到本地
        storageType: 'sessionStorage',
        path: ['configInfo']
      },
      {
        storeName: ['test'], // 对于特定store进行持久化,空或者不传,则对所有的store进行缓存到本地
        storageType: 'sessionStorage'
      },
      {
        storeName: ['test1'], // 对于特定store进行持久化,空或者不传,则对所有的store进行缓存到本地
        storageType: 'localStorage'
      }
    ]
  })
)

存储之后的结果,可以在浏览器里看到

1686891701238.jpg

1686891710517.jpg

参考库

github.com/Seb-L/pinia…

当时是参考了网路上一个开源库的实现

这个库如果使用,需要每个store下,都进行配置。

我们开发时,不可能只定义一个store,一般是按功能,模块划分代码,保证可读性。

所以我觉得使用这个库,开发成本更大

因此在这个基础上自行写了一套持久化插件,在入口处全局管理

export const useUserStore = defineStore('storeUser', {
  state () {
    return {
      firstName: 'S',
      lastName: 'L',
      accessToken: 'xxxxxxxxxxxxx',
    }
  },
  // 插件配置  
  persist: {
    enabled: true,
    strategies: [
      {
        key: 'user',  //自定义 Key值
        storage: localStorage,  // 选择存储方式
      },
    ],
  },
})

总结

我现在开发的持久化插件,一定程度上,增加了使用者的心智负担,需要去了解配置项的规则。

持久化存储的场景非常多,对于小型页面小型项目,直接在修改store,再手动设置一次sessionStroage,在页面中使用的时候,再去主动取一下sessionStorage 即可,没有任何问题。

但是如果是对于多人维护的大型项目,如果这么写,随着迭代,将搞不清楚到底哪些数据存在了session中,在什么时机存储的,无法统一管理。

有这样一个插件,就可以在全局统一配置,增删改查在入口文件统一管理。


相关文章
|
5月前
|
JavaScript 前端开发 安全
Vue 3
Vue 3以组合式API、Proxy响应式系统和全面TypeScript支持,重构前端开发范式。性能优化与生态协同并进,兼顾易用性与工程化,引领Web开发迈向高效、可维护的新纪元。(238字)
804 139
|
5月前
|
缓存 JavaScript 算法
Vue 3性能优化
Vue 3 通过 Proxy 和编译优化提升性能,但仍需遵循最佳实践。合理使用 v-if、key、computed,避免深度监听,利用懒加载与虚拟列表,结合打包优化,方可充分发挥其性能优势。(239字)
411 1
|
6月前
|
开发工具 iOS开发 MacOS
基于Vite7.1+Vue3+Pinia3+ArcoDesign网页版webos后台模板
最新版研发vite7+vue3.5+pinia3+arco-design仿macos/windows风格网页版OS系统Vite-Vue3-WebOS。
678 12
|
5月前
|
JavaScript 安全
vue3使用ts传参教程
Vue 3结合TypeScript实现组件传参,提升类型安全与开发效率。涵盖Props、Emits、v-model双向绑定及useAttrs透传属性,建议明确声明类型,保障代码质量。
479 0
|
7月前
|
缓存 前端开发 大数据
虚拟列表在Vue3中的具体应用场景有哪些?
虚拟列表在 Vue3 中通过仅渲染可视区域内容,显著提升大数据列表性能,适用于 ERP 表格、聊天界面、社交媒体、阅读器、日历及树形结构等场景,结合 `vue-virtual-scroller` 等工具可实现高效滚动与交互体验。
690 1
|
7月前
|
缓存 JavaScript UED
除了循环引用,Vue3还有哪些常见的性能优化技巧?
除了循环引用,Vue3还有哪些常见的性能优化技巧?
394 0
|
8月前
|
JavaScript
vue3循环引用自已实现
当渲染大量数据列表时,使用虚拟列表只渲染可视区域的内容,显著减少 DOM 节点数量。
194 0
|
9月前
|
JavaScript API 开发者
Vue框架中常见指令的应用概述。
通过以上的详细解析,你应该已经初窥Vue.js的指令的威力了。它们是Vue声明式编程模型的核心之一,无论是构建简单的静态网站还是复杂的单页面应用,你都会经常用到。记住,尽管Vue提供了大量预定义的指令,你还可以创建自定义指令以满足特定的需求。为你的Vue应用程序加上这些功能增强器,让编码变得更轻松、更愉快吧!
170 1
|
9月前
|
JavaScript 前端开发 UED
Vue 项目中如何自定义实用的进度条组件
本文介绍了如何使用Vue.js创建一个灵活多样的自定义进度条组件。该组件可接受进度段数据数组作为输入,动态渲染进度段,支持动画效果和内容展示。当进度超出总长时,超出部分将以红色填充。文章详细描述了组件的设计目标、实现步骤(包括props定义、宽度计算、模板渲染、动画处理及超出部分的显示),并提供了使用示例。通过此组件,开发者可根据项目需求灵活展示进度情况,优化用户体验。资源地址:[https://pan.quark.cn/s/35324205c62b](https://pan.quark.cn/s/35324205c62b)。
427 0
|
10月前
|
JavaScript 前端开发 API
Vue 2 与 Vue 3 的区别:深度对比与迁移指南
Vue.js 是一个用于构建用户界面的渐进式 JavaScript 框架,在过去的几年里,Vue 2 一直是前端开发中的重要工具。而 Vue 3 作为其升级版本,带来了许多显著的改进和新特性。在本文中,我们将深入比较 Vue 2 和 Vue 3 的主要区别,帮助开发者更好地理解这两个版本之间的变化,并提供迁移建议。 1. Vue 3 的新特性概述 Vue 3 引入了许多新特性,使得开发体验更加流畅、灵活。以下是 Vue 3 的一些关键改进: 1.1 Composition API Composition API 是 Vue 3 的核心新特性之一。它改变了 Vue 组件的代码结构,使得逻辑组
2130 0

热门文章

最新文章