仓库持久化——以vue3为例

在开发的过程当中我们会遇到仓库持久化的问题,今天给大家分享一下仓库持久化的基本用法和原理,状态管理库有两种一种是Vuex,一种是Pinia,两种都分享一下。

仓库持久化有专门的插件可以使用,此篇文章没有采用插件,而是用了自定义的函数插件来实现的供大家参考

此文章以vue3为例,UI组件用的是Naive UI

Vuex

创建vuex仓库

下载并配置vuex

//这里的 @next 是为了安装 Vuex 4,它适用于 Vue 3。
pnpm add vuex@next

配置Vuex仓库

下载完成后配置仓库,在main.ts引入vuex

//main.ts

import { createApp } from 'vue'
import vuex from './storeVuex/index'

const app = createApp(App)
app.use(vuex).mount('#app')

在src下创建文件夹 storeVuex,以及存放模块的modules文件夹和一些ts文件,这是Vuex仓库的目录结构

小仓库  user.ts

//user.ts

const user = {
  namespaced: true,
  state: {
    name: '周杰伦',
    age: 35,
    role: '歌手',
  },
  mutations: {
    setName(state, newName) {
      state.name = newName
    },
    setAge(state, newAge) {
      state.age = newAge
    },
    setRole(state, newRole) {
      state.role = newRole
    },
  },
  actions: {
    updateName({ commit }, newName) {
      commit('setName', newName)
    },
    updateAge({ commit }, newAge) {
      commit('setAge', newAge)
    },
    //修改State中的值
    update({ commit }, payload) {
      commit('setName', payload.name)
      commit('setAge', payload.age)
      commit('setRole', payload.role)
    },
  },
}
export default user

在大仓库中引入小仓库  index.ts

//index.ts

import { createStore } from 'vuex'
import user from './modules/user'
//这里引入我们自定义的插件,其实就是一个函数
import myPlugin from './myPlugin.ts'
const store: any = createStore({
  modules: {
    test: user,
  },
  //plugin的执行时机是在仓库初始化完成之后调用
  plugins: [myPlugin],
})
export default store

编写插件函数

自定义插件  myPlugin.ts

编写我们的插件函数。

//myPlugin.ts

const myPlugin = (store) => {
  //store 是仓库对象

  //存储数据
  //beforeunload事件——用户正在离开
  window.addEventListener('beforeunload', (e) => {
    localStorage.setItem('USER', JSON.stringify(store.state))
  })
  // 取数据
  const user = localStorage.getItem('USER')
  if (user) {
    store.replaceState(JSON.parse(user))
  }
}
export default myPlugin

使用仓库

在页面中使用store

<template>
  <div>
    <div class="store-container">
      <h2>vuex</h2>
      <n-form
        ref="formRef"
        inline
        label-width="auto"
        label-placement="left"
        :model="formJay"
        :size="size"
      >
        <n-form-item label="姓名" path="name">
          <n-input v-model:value="formJay.name" placeholder="输入姓名" />
        </n-form-item>
        <n-form-item label="年龄" path="age">
          <n-input v-model:value="formJay.age" placeholder="输入年龄" />
        </n-form-item>
        <n-form-item label="角色" path="role">
          <n-input v-model:value="formJay.role" placeholder="角色" />
        </n-form-item>
        <n-form-item>
          <n-button type="primary" attr-type="button" @click="updateJay">
            提交
          </n-button>
        </n-form-item>
      </n-form>
    </div>
  </div>
</template>
<script lang="ts" setup>
import { useStore } from 'vuex'
import { onMounted, ref } from 'vue'

const userStore = useStore()
const formRef = ref<any>()

const size = ref<'small' | 'medium' | 'large'>('medium')
//取值
const formJay = ref<any>({
  name: undefined,
  age: undefined,
  role: undefined,
})
const updateJay = () => {
//更新数据
  userStore.dispatch('user/update', formJay.value)
}
onMounted(() => {
//取值 赋值
  formJay.value = userStore.state.user
})
</script>
<style lang="scss" scoped>
.store-container {
  width: 100%;
  height: 400px;
  //text-align: center;
  margin-top: 100px;
  h2 {
    font-size: 18px;
    font-weight: 600;
    color: #333;
    margin-bottom: 20px;
  }
}
</style>

查看状态

修改完数据之后——点击提交,然后刷新页面,数据不会丢失,说明仓库状态持久化成功了

我们是将数据存储在了 localStorage,所以要在localstorage中查看数据是否保存成功,USER是在插件函数中 监听beforeunload 存的值

Pinia

创建Pinia仓库

pnpm add pinia

配置Pinia仓库

myPlugin是自己编写的插件函数

//main.ts

import { createApp } from 'vue'
import pinia from './store'
//pinia使用自定义插件
import piniaPlugin from './store/myPlugin'
pinia.use(piniaPlugin)
const app = createApp(App)
app.use(pinia).mount('#app')

 在src下创建文件夹 store,以及存放模块的modules文件夹和一些ts文件,这是Pinia仓库的目录结构

创建小仓库 user.ts

//user.ts
import { defineStore } from 'pinia'
const useUserStore = defineStore('User', {
  state: () => ({
    name: '林俊杰',
    age: 35,
    role: '歌手',
  }),
  actions: {
    updateName(newName) {
      this.name = newName
    },
    updateAge(newAge) {
      this.age = newAge
    },
    update({ name, age, role }) {
      this.name = name
      this.age = age
      this.role = role
    },
  },
})
export default useUserStore

 创建大仓库 index.ts

//index.ts
import { createPinia } from 'pinia'
import { useUserStore } from './modules/user'
//创建大仓库
const pinia = createPinia()
//对外暴露:入口文件需要安装仓库
export default pinia

编写插件函数

Pinia的context和vuex不同,Pinia在使用的时候接收到的 context是仓库的上下文,每个仓库有自己的上下文,通过在控制台的输出可以看到 store中的$id 可以区分出来是哪个仓库,所以我们在往localStorage中存数据的时候,可以通过$id的值做区分

//myPlugin.ts
const KEY = 'PINIA_STORE_'
const myPlugin = (context) => {
  console.log(context)
  const { store } = context
  const KEY_ = KEY + store.$id
  window.addEventListener('beforeunload', (e) => {
    localStorage.setItem(KEY_, JSON.stringify(store.$state))
  })
  const user = localStorage.getItem(KEY_)
  if (user) {
    store.$patch(JSON.parse(user))
  }
}
export default myPlugin

使用仓库

在页面使用仓库

<template>
  <div>
    <div class="store-container">
      <h2>pinia</h2>
      <n-form
        ref="formRef"
        inline
        label-width="auto"
        label-placement="left"
        :model="formJJ"
        :size="size"
      >
        <n-form-item label="姓名" path="name">
          <n-input v-model:value="formJJ.name" placeholder="输入姓名" />
        </n-form-item>
        <n-form-item label="年龄" path="age">
          <n-input v-model:value="formJJ.age" placeholder="输入年龄" />
        </n-form-item>
        <n-form-item label="角色" path="role">
          <n-input v-model:value="formJJ.role" placeholder="角色" />
        </n-form-item>
        <n-form-item>
          <n-button type="primary" attr-type="button" @click="updateJJ">
            提交
          </n-button>
        </n-form-item>
      </n-form>
    </div>
  </div>
</template>
<script lang="ts" setup>
import { onMounted, ref } from 'vue'
import useUserStore from '@/store/modules/user'

const formRef = ref<any>()
const userStore = useUserStore()

const size = ref<'small' | 'medium' | 'large'>('medium')

const formJJ = ref<any>({
  name: undefined,
  age: undefined,
  role: undefined,
})

onMounted(() => {
  //取值
  formJJ.value = userStore.$state
})
const updateJJ = () => {
  //修改值
  userStore.update(formJJ.value)
}
</script>
<style lang="scss" scoped>
.store-container {
  width: 100%;
  height: 400px;
  margin-top: 100px;
  h2 {
    font-size: 18px;
    font-weight: 600;
    color: #333;
    margin-bottom: 20px;
  }
}
</style>

 查看状态

修改完数据之后——点击提交,然后刷新页面,数据不会丢失,说明仓库状态持久化成功了

我们是将数据存储在了 localStorage,所以要在localstorage中查看数据是否保存成功,PINIA_STORE_User 是在插件函数中 监听beforeunload 存的值

完结 !!!

### 如何使用 Vue3 构建任务管理系统 #### 项目初始化与环境搭建 为了创建基于 Vue3 的任务管理系统,首先需要安装并配置开发环境。推荐通过 `vue-cli` 或者 Vite 来快速启动一个新的 Vue 应用程序。 如果选择 Git 方式获取现有模板,则可以通过如下命令克隆仓库[^2]: ```bash git clone https://github.com/jeecgboot/jeecgboot-vue3.git ``` #### 创建基本组件结构 在构建任务管理系统时,通常会涉及到多个功能模块的设计,比如任务列表展示、详情页浏览等。对于这些需求,应该按照单文件组件的形式来组织代码逻辑。 假设要实现一个简单的待办事项应用作为入门案: 1. **TaskList.vue**: 显示所有未完成的任务项; 2. **TaskItem.vue**: 单个任务条目的样式和交互行为定义; 3. **AddTaskForm.vue**: 提供表单让用户输入新的任务描述; #### 数据存储方案设计 考虑到实际应用场景中的复杂度,可能还需要引入状态管理模式 Vuex 或 Pinia 来集中处理全局共享的数据流控制问题。此外,也可以考虑利用本地浏览器缓存机制(LocalStorage / SessionStorage),或是连接远程 RESTful API 接口来进行持久化保存。 #### 功能实现细节 针对具体的功能点——如查看特定任务的信息,可以在相应的路由视图内加载完整的记录字段集合,并允许用户执行进一步的操作,像编辑、删除等功能按钮设置[^3]。 以下是简化版的 TaskItem 组件示: ```javascript // src/components/TaskItem.vue <template> <div class="task-item"> <h4>{{ task.title }}</h4> <p>工号: {{ task.employeeId }} | 姓名: {{ task.name }} | 部门: {{ task.department }}</p> <button @click="$emit(&#39;view-detail&#39;, task.id)">查看详情</button> </div> </template> <script setup> defineProps({ task: Object, }); const emit = defineEmits([&#39;view-detail&#39;]); </script> ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值