Vue3基本使用Pinia,Pinia和vuex的区别 pinia的基本使用 Pinia状态持久化 pinia-plugin-persistedstate的使用 详细说明!!!

Pinia是Vue的状态管理库,设计类似于Vue的CompositionAPI,提供更简单的API和更好的TypeScript支持。相比于Vuex,Pinia消除了mutations,简化了modules结构,并且有更好的开发者工具集成。安装Pinia后,通过defineStore定义Store,使用storeToRefs保持响应式。Pinia还支持状态持久化。

目录

什么是Pinia呢?

我们都已经有 Vuex 了为什么还要用 Pinia 呢

与 Vuex 相比,Pinia 有很多的优势

安装pinia

定义一个存储库 Store

认识 Store

定义一个store

使用定义的Store

操作State(一) 

操作State(二)

认识和定义Getters

 访问Getters

认识和定义Actions

Actions执行异步操作


什么是Pinia呢?

Pinia(发音为/piːnjʌ/,如英语中的“peenya”)是最接近piña(西班牙语中的菠萝)的词

         Pinia开始于大概2019年,最初是作为一个实验为Vue重新设计状态管理,让它用起来像组合式API(Composition API)

         从那时到现在,最初的设计原则依然是相同的,并且目前同时兼容Vue2、Vue3,也并不要求你使用Composition API;

         Pinia本质上依然是一个状态管理的库,用于跨组件页面进行状态共享(这点和Vuex、Redux一样);

我们都已经有 Vuex 了为什么还要用 Pinia 呢

        Pinia 最初是为了探索 Vuex 的下一次迭代会是什么样子,结合了 Vuex 5 核心团队 讨论中的许多想法;

        最终,团队意识到Pinia已经实现了Vuex5中大部分内容,所以最终决定用Pinia来代替Vuex;

        与 Vuex 相比,Pinia 提供了一个更简单的 API,具有更少的仪式,提供了 Composition-API 风格的 API;

        最终要的是,在与 TypeScript 一起使用时具有可靠的类型判断支持;

与 Vuex 相比,Pinia 有很多的优势

        比如 mutations 不再存在:

                √  他们经常被认为是 非常冗长;

                √  他们最初带来的 devtools 集成,但这不再是问题;

        更友好的TypeScript支持,Vuex 之前对TS的支持很不友好;

        不再有modules的嵌套结构:

                √  你可以灵活使用每一个 store,他们是通过扁平化的方式来相互使用的;

        也不会再有命名空间的概念,不需要记住他们的复杂关系;

安装pinia

用你最喜欢的包管理器安装 pinia

yarn add pinia
# 或者使用 npm
npm install pinia

定义一个存储库 Store

import { createPinia } from "pinia"

const pinia = createPinia()

export default pinia

 在vue工程目录下的src目录下创建一个 stores 文件下 然后创建一个 index.js的文件 并且在idnex.js文件内创建pinia并导出 之后在 main.js里引入并且使用 stores

import pinia from './stores'

createApp(App).use(pinia).use(router).mount('#app')

认识 Store

◼ 什么是Store?

         一个 Store (如 Pinia)是一个实体,它会持有为绑定到你组件树状态和业务逻辑,也就是保存了全局的状态;

         它有点像始终存在,并且每个人都可以读取和写入的组件

         你可以在你的应用程序中定义任意数量的Store来管理你的状态

◼ Store有三个核心概念:

         state、getters、actions

         等同于组件的data、computed、methods;

         一旦 store 被实例化,你就可以直接在 store 上访问 state、getters 和 actions 中定义的任何属性;

定义一个store

         我们需要知道 Store 是使用 defineStore() 定义的,

         并且它需要一个唯一名称,作为第一个参数传递;

import { defineStore } from "pinia"

const useCounter = defineStore('count', {
  // defineStore(id(一个储存库标识))
  state: () => ({
    username: '桥志',
    age: 20,
    like: 'watermelon-ice',
    users: [
      { id: 1, name: 'HachimanC', age: 18 },
      { id: 2, name: '大吉', age: 20 },
      { id: 3, name: '桥志三', age: 21 }
    ]
  })
})

export default useCounter

◼ 这个 name,也称为 id,是必要的,Pinia 使用它来将 store 连接到 devtools。

◼ 返回的函数统一使用useX作为命名方案,这是约定的规范;

使用定义的Store

◼ Store在它被使用之前是不会创建的,我们可以通过调用use函数来使用Store:

  <div>姓名: {{ username }}</div>
  <div>年龄: {{ age }}</div>
  <div>喜欢: {{ like }}</div>

<script setup>
import useInfo from '@/stores/information'
import { toRefs } from 'vue'
import { storeToRefs } from 'pinia'

const infoStore = useInfo()

const {username} = infoStore // 不是响应式
const { username } = toRefs(infoStore) // 是响应式
const { username, age, like } = storeToRefs(infoStore) // 是响应式
</script>

注意Store获取到后不能被解构,那么会失去响应式

         为了从 Store 中提取属性同时保持其响应式,您需要使用storeToRefs()

操作State(一) 

读取和写入 state

         默认情况下,您可以通过 store 实例访问状态来直接读取和写入状态;

const editPiniaHandler = () => {
  // 一个一个修改
  infoStore.username += '三'
  infoStore.age += 1
  infoStore.like = 'girl'
}

重置 State

         你可以通过调用 store 上的 $reset() 方法将状态 重置 到其初始值;

const resetPiniaHandler = () => {
  infoStore.$reset()
}

操作State(二)

◼ 改变State:

         除了直接用 store.counter++ 修改 store,你还可以调用 $patch 方法;

         它允许您使用部分“state”对象同时应用多个更改

  // 一次性修改
  infoStore.$patch({
    username: 'HachimanC',
    age: 21,
  })

◼ 替换State:

         您可以通过将其 $state 属性设置为新对象来替换 Store 的整个状态:

  // 替换 state 为新对象
  const oldState = infoStore.$state
  useInfo.$state = {
    name: 'HachimanC',
    age: '22',
    like: 'girl',
  }
  console.log(oldState === infoStore.$state)

认识和定义Getters

◼ Getters相当于Store的计算属性:

         它们可以用 defineStore() 中的 getters 属性定义;

         getters中可以定义接受一个state作为参数的函数

 访问Getters

◼ Getters中访问自己的其他Getters:

         我们可以通过this来访问到当前store实例的所有其他属性;

◼ Getters也可以返回一个函数,这样就可以接受参数:

  <!-- getters使用部分 -->
  <div>doubleAge: {{ infoStore.doubleAge }}</div>
  <div>doubleAgeAddOne: {{ infoStore.doubleAgeAddOne }}</div>
  <div>查找id是2的用户: {{ infoStore.getUserById(2) }}</div>
  <div>查找id是3的用户: {{ infoStore.getUserById(3) }}</div>
  <div>getters使用其他储存库信息: {{ infoStore.showMessage }}</div>
  <hr />

认识和定义Actions

Actions 相当于组件中的 methods

         可以使用 defineStore() 中的 actions 属性定义,并且它们非常适合定义业务逻辑;

 ◼ 和getters一样,在action中可以通过this访问整个store实例的所有操作;

Actions执行异步操作

◼ Actions中是支持异步操作的,并且我们可以编写异步函数,在函数中使用await;

 

  <!-- avtions 使用部分 -->
  <div>{{ infoStore.age }}</div>
  <button @click="addAgeHandler">actions操作</button>
  <!-- 展示avtions异步请求来的数据 -->
  <ul>
    <template v-for="item in homeStore.banners" :key="item">
      <li>{{item.title}}</li>
    </template>
  </ul>

Pinia状态持久化

用你喜欢的包管理器安装依赖:

pnpm i pinia-plugin-persistedstate

npm i pinia-plugin-persistedstate

yarn add pinia-plugin-persistedstate

 将插件添加到 pinia 实例上

import { createPinia } from 'pinia'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'

const pinia = createPinia()
pinia.use(piniaPluginPersistedstate)

创建 Store 时,将 persist 选项设置为 true

使用选项式 Store 语法:

import { defineStore } from 'pinia'

export const useStore = defineStore('main', {
  state: () => {
    return {
      someState: '你好 pinia',
    }
  },
  persist: true,
})

或者使用组合式 Store 语法:

import { defineStore } from 'pinia'

export const useStore = defineStore(
  'main',
  () => {
    const someState = ref('你好 pinia')
    return { someState }
  },
  {
    persist: true,
  }
)

现在,你的整个 Store 将使用默认持久化配置保存。

配置持久化的数据会存到 localStore里。

<think>我们正在处理一个关于在Vue3使用Pinia持久化插件pinia-plugin-persistedstate的问题。根据引用内容,我们可以整理出以下步骤: 目标:在Vue3项目中使用Pinia进行状态管理,并使用pinia-plugin-persistedstate插件实现状态持久化。 步骤: 1. 安装必要的包:pinia pinia-plugin-persistedstate。 2. 创建一个pinia实例,并将插件添加到该实例上。 3. 在定义store时,通过设置`persist: true`来启用持久化。 4. 在main.ts(或main.js)中将pinia实例挂载到Vue应用上。 5. 在组件中使用store。 另外,引用中提到了在uni-app等环境中可能需要自定义存储方式(如使用uni-app的存储API),但一般情况下在浏览器中默认使用localStorage。 根据引用[4],注意不要使用已经废弃的pinia-plugin-persist,而应使用pinia-plugin-persistedstate。 现在,我们按照步骤详细说明: ### 1. 安装 ```bash npm install pinia pinia-plugin-persistedstate # 或者 yarn add pinia pinia-plugin-persistedstate # 或者 pnpm add pinia pinia-plugin-persistedstate ``` ### 2. 创建配置Pinia实例 在项目的入口文件(如main.ts或main.js)中: ```typescript import { createApp } from &#39;vue&#39; import { createPinia } from &#39;pinia&#39; import piniaPluginPersistedstate from &#39;pinia-plugin-persistedstate&#39; import App from &#39;./App.vue&#39; // 创建Pinia实例 const pinia = createPinia() // 使用持久化插件 pinia.use(piniaPluginPersistedstate) const app = createApp(App) app.use(pinia) app.mount(&#39;#app&#39;) ``` ### 3. 定义Store并启用持久化 在store文件中(例如src/store/user.ts): ```typescript import { defineStore } from &#39;pinia&#39; import { ref } from &#39;vue&#39; export const useUserStore = defineStore(&#39;user&#39;, () => { const token = ref(&#39;&#39;) const username = ref(&#39;&#39;) function setUserInfo(newToken: string, newUsername: string) { token.value = newToken username.value = newUsername } return { token, username, setUserInfo } }, { persist: true // 开启持久化 }) ``` ### 4. 在组件中使用Vue组件中,你可以像这样使用store: ```vue <script setup lang="ts"> import { useUserStore } from &#39;@/store/user&#39; const userStore = useUserStore() // 设置用户信息 userStore.setUserInfo(&#39;token123&#39;, &#39;John Doe&#39;) // 直接访问状态 console.log(userStore.token) // 输出 &#39;token123&#39; </script> <template> <div> <p>用户名: {{ userStore.username }}</p> </div> </template> ``` ### 自定义持久化配置(可选) 如果你需要自定义存储方式(比如在uni-app中使用uni.setStorageSync),可以在创建pinia插件时传入配置。例如,根据引用[3]的示例: ```typescript // 在创建pinia实例的地方(如单独的pinia.ts文件) import { createPinia } from &#39;pinia&#39; import { createPersistedState } from &#39;pinia-plugin-persistedstate&#39; const pinia = createPinia() pinia.use(createPersistedState({ storage: { getItem(key: string): string | null { // 使用uni-app的存储API return uni.getStorageSync(key) }, setItem(key: string, value: string) { uni.setStorageSync(key, value) } } })) export default pinia ``` 然后在main.ts中引入这个配置好的pinia实例。 ### 注意事项 - 默认情况下,持久化的数据会存储在localStorage中,key为store的id(如上面例子中的&#39;user&#39;)。 - 如果需要进一步配置(如指定要持久化的字段、使用sessionStorage等),可以在定义store时传入一个对象而不是布尔值。例如: ```typescript persist: { storage: sessionStorage, // 使用sessionStorage paths: [&#39;token&#39;] // 只持久化token字段 } ``` -使用组合式API定义store(setup语法)时,注意返回的状态必须是需要持久化状态。 ### 验证持久化效果 在浏览器中,打开开发者工具,进入Application选项卡,在Local Storage部分可以看到以store id为键存储的数据。 ### 常见问题 - 如果遇到类型错误(如引用[4]中的重载错误),请确保安装的是`pinia-plugin-persistedstate`而不是其他插件。 - 在SSR(服务器端渲染)环境中,需要谨慎使用,因为localStorage在服务器端不可用。 通过以上步骤,你应该能够在Vue3项目中成功使用Piniapinia-plugin-persistedstate实现状态持久化。 ### 相关问题 1. 如何在Pinia持久化时指定存储的key? 2. 如何避免某些字段被持久化3. 在Vue3的setup语法中如何正确使用Pinia store? 4. 如何重置Pinia store的持久化数据? 5. 在TypeScript项目中如何为Pinia store提供类型支持? [^1]: Vue3基本使用PiniaPiniavuex区别 pinia基本使用 Pinia状态持久化 pinia-plugin-persistedstate的... [^2]: 在vue3组合式API中使用pinia-plugin-persistedstate持久化存储pinia的state [^3]: vue3 使用 piniapinia-plugin-persistedstate 持久化数据管理 [^4]: vue3+vite+pinia+pinia-plugin-persistedstate持久化存储</think># 在 Vue3使用 Pinia pinia-plugin-persistedstate 实现状态持久化 下面是如何在 Vue3 项目中完整使用 Pinia 状态管理库及其持久化插件 pinia-plugin-persistedstate详细指南: ## 安装依赖 首先安装必要的依赖包: ```bash npm install pinia pinia-plugin-persistedstate # 或使用 yarn yarn add pinia pinia-plugin-persistedstate # 或使用 pnpm pnpm add pinia pinia-plugin-persistedstate ``` ## 配置 Pinia 持久化插件 ### 1. 创建 Pinia 实例并添加插件 在 `src/main.ts` 文件中配置: ```typescript import { createApp } from &#39;vue&#39; import { createPinia } from &#39;pinia&#39; import piniaPluginPersistedstate from &#39;pinia-plugin-persistedstate&#39; import App from &#39;./App.vue&#39; // 创建 Pinia 实例 const pinia = createPinia() // 添加持久化插件 pinia.use(piniaPluginPersistedstate) const app = createApp(App) // 使用 Pinia app.use(pinia) app.mount(&#39;#app&#39;) ``` ### 2. 创建 Store 并启用持久化 在 `src/store/userStore.ts` 中定义 store: ```typescript import { defineStore } from &#39;pinia&#39; import { ref, computed } from &#39;vue&#39; export const useUserStore = defineStore(&#39;user&#39;, () => { // 用户状态 const token = ref(localStorage.getItem(&#39;token&#39;) || &#39;&#39;) const userInfo = ref({ id: &#39;&#39;, name: &#39;访客&#39;, email: &#39;&#39;, avatar: &#39;&#39;, }) // 计算属性 const isLoggedIn = computed(() => !!token.value) // 登录操作 function login(userData: any) { token.value = userData.token userInfo.value = userData } // 登出操作 function logout() { token.value = &#39;&#39; userInfo.value = { id: &#39;&#39;, name: &#39;访客&#39;, email: &#39;&#39;, avatar: &#39;&#39; } } return { token, userInfo, isLoggedIn, login, logout } }, { // 启用持久化 persist: true }) ``` ## 自定义持久化配置(可选) 如果需要自定义存储方式(如在 uni-app 中使用 uniStorage): ```typescript // src/stores/pinia.ts import { createPinia } from &#39;pinia&#39; import { createPersistedState } from &#39;pinia-plugin-persistedstate&#39; export const pinia = createPinia() pinia.use(createPersistedState({ storage: { getItem: (key: string) => { return uni.getStorageSync(key) }, setItem: (key: string, value: string) => { uni.setStorageSync(key, value) }, removeItem: (key: string) => { uni.removeStorageSync(key) } } })) // 然后在 main.ts 中导入并使用这个配置好的 pinia 实例 ``` ## 在组件中使用 Store 在 Vue 组件中使用定义好的 store: ```vue <script setup lang="ts"> import { useUserStore } from &#39;@/stores/userStore&#39; const userStore = useUserStore() // 登录操作 const handleLogin = () => { userStore.login({ token: &#39;abc123xyz&#39;, id: &#39;user001&#39;, name: &#39;张三&#39;, email: &#39;zhangsan@example.com&#39;, avatar: &#39;/avatar.png&#39; }) } // 登出操作 const handleLogout = () => { userStore.logout() } </script> <template> <div v-if="userStore.isLoggedIn"> <h2>欢迎, {{ userStore.userInfo.name }}</h2> <img :src="userStore.userInfo.avatar" alt="头像" /> <button @click="handleLogout">退出登录</button> </div> <div v-else> <button @click="handleLogin">登录</button> </div> </template> ``` ## 高级配置选项 在定义 store 时,可以配置更详细持久化选项: ```typescript export const useSettingsStore = defineStore(&#39;settings&#39;, () => { const theme = ref(&#39;light&#39;) const fontSize = ref(16) const notifications = ref(true) return { theme, fontSize, notifications } }, { persist: { // 只持久化指定字段 paths: [&#39;theme&#39;, &#39;fontSize&#39;], // 自定义存储键名 key: &#39;app-settings&#39;, // 使用 sessionStorage 替代 localStorage storage: sessionStorage, // 自定义序列化反序列化方法 serialize: JSON.stringify, deserialize: JSON.parse, // 在恢复状态前执行钩子 beforeRestore: (ctx) => { console.log(`即将恢复状态: ${ctx.store.$id}`) }, // 在恢复状态后执行钩子 afterRestore: (ctx) => { console.log(`状态恢复完成: ${ctx.store.$id}`) } } }) ``` ## 常见问题解决 1. **类型错误问题**: - 确保使用正确的包名:`pinia-plugin-persistedstate` - 不要使用已废弃的 `pinia-plugin-persist` - 如果遇到类型错误,尝试更新 TypeScript Vue 相关依赖 2. **SSR 兼容问题**: ```typescript // 在 SSR 环境中安全使用 persist: { storage: typeof window !== &#39;undefined&#39; ? localStorage : null } ``` 3. **状态更新未触发持久化**: - 确保直接修改状态属性(如 `userStore.token = &#39;new&#39;`) - 避免直接替换整个状态对象 ## 持久化原理 pinia-plugin-persistedstate 的工作流程: 1. 在 store 初始化时,从存储中读取并恢复状态 2. 监听 store 的变化 3. 当状态变化时,将新状态序列化后存入存储 4. 在页面加载时,从存储中读取并恢复状态 ## 相关资源 - [Pinia 官方文档](https://pinia.vuejs.org/) - [pinia-plugin-persistedstate 文档](https://prazdevs.github.io/pinia-plugin-persistedstate/) --- ### 相关问题 1. Pinia Vuex 有哪些主要区别? 2. 如何在 Pinia 中处理异步操作? 3. 如何实现 Pinia store 之间的相互调用? 4. 在 SSR 应用中如何安全使用 Pinia 持久化? 5. 如何为 Pinia store 添加 TypeScript 类型支持? > 示例代码基于引用内容[^1][^2][^3][^4]实现,展示了在 Vue3使用 Pinia 持久化插件的最佳实践。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值