Vue3 状态管理 -pinia使用教程
文章目录
1.Pinia介绍
Pinia 是 Vue 的专属的最新状态管理库 ,是 Vuex 状态管理工具的替代品
Pinia优势:
1.提供了封建简单的API(去掉了 mutation)
2.提供符合这是风格的API(和 Vue3 新语法统一)
3.去掉了 modules 的概念,每一个 store 都是一个独立的模块
4.配合 TypeScript 更加友好,提供可靠类型推断
2.手动添加Pinia到Vue项目
在以后的项目开发中,并不需要手动添加,这里只是介绍全流程
创建 vue 项目
npm create vue@latest

项目初始化完成,可执行以下命令:
cd vue3-pinia-demo
npm install
npm run dev
创建成功,然后清理创建好的模板
- 删除src 下的 assets 和 components
- main.js 中删除import ‘./assets/main.css’
- app.vue 中删除 script 中代码 ,清空 template 代码 ,删除 style 标签内的代码
<script setup>
</script>
<template>
<div>
<h1>App.vue 根组件</h1>
</div>
</template>
<style scoped>
</style>
创建两个组件,方便模拟 pinia 的使用
按照官方文档安装 pinia 到项目中:
pinia 开始官方文档
下载 pinia
npm install pinia
创建实例写入 main.js
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
const pinia = createPinia()
const app = createApp(App)
app.use(pinia)
app.mount('#app')
3.Pinia基础使用
1.定义store
2.组件使用store
3.1 定义store
这里用和 Vue3 语法风格更接近的Setup Store定义仓库
在 src 下面创建 store 文件夹,store 文件下创建 js 文件定义仓库
基本结构:
//导入定义仓库的包
import { defineStore } from 'pinia'
//导入定义数据的包
import {ref} from 'vue'
//定义 store
//define(仓库唯一标识,()=>{...})
defineStore('counter',()=>{
//声明数据 state-count
//声明数据操作的方法 action
//声明基于数据派生的计算属性 getters
})
完整结构:
//导入定义仓库的包
import { defineStore } from 'pinia'
//导入定义数据的包
import {ref} from 'vue'
//定义 store
//defineStore(仓库唯一标识,()=>{...})
//defineStore返回的是函数,用一个函数名接收,方便后续的使用
export const useCounterStore= defineStore('counter',()=>{
//声明数据 state-count
const count=ref(0)
//声明数据 state-msg
const msg=ref('hello pinia')
//声明数据操作的方法 action
//声明基于数据派生的计算属性 getters
return{
count,
msg
}
})
3.2 组件使用store
到 app.vue页面使用数据
- 导包
- 定义接收
- 使用
<script setup>
import Son1Com from './components/son1.vue'
import Son2Com from './components/son2.vue'
// 1.导包
import {useCounterStore} from './store/counter'
// 2.定义 接收
const counterStore=useCounterStore()
</script>
<template>
<div>
<!-- 使用 -->
<h1>App.vue 根组件
-{{ counterStore.count }}
-{{ counterStore.msg }}
</h1>
<Son1Com></Son1Com>
<Son2Com></Son2Com>
</div>
</template>
<style scoped>
</style>

在其他组件使用的过程中,使用也同理
使用数据操作的方法-action
- 定义操作方法
- return出去
export const useCounterStore= defineStore('counter',()=>{
//声明数据 state-count
const count=ref(0)
//声明数据 state-msg
const msg=ref('hello pinia')
//声明数据操作的方法 action
const addCount =()=>{
count.value++
}
const subCount =()=>{
count.value--
}
//声明基于数据派生的计算属性 getters
return{
count,
msg,
addCount,
subCount
}
})
son1 和 son2 中拿这两个方法

使用 getters(计算属性)

3.3 action异步实现
方式:异步action函数的写法和组件中获取异步数据的写法完全一致
-
接口地址:http://geek.itheima.net/v1_0/channels
-
请求方式:get
-
请求参数:无
使用 axios 接收数据,先下载 axios 的包,并且导入进去
接收数据
//声明数据操作的方法
const getList=async()=>{
//支持异步
const {data:{data}}=await axios.get('http://geek.itheima.net/v1_0/channels')
}
讲解一下这种写法:
await axios.get(…)
- 这是通过 axios 发送 GET 请求
- await 表示等待它返回结果(是一个 Promise)
- 返回结构如下(假设返回成功)
data:{data}拿的 response.data.data
虽然接口数据是这样的,但是 axios 本身就会封装一个 data,所以拿的是 data.data
{
"data": {
"channels": [
{
"id": 0,
"name": "推荐"
},
不用解构的写法的等价写法
const getList = async () => {
const res = await axios.get('http://geek.itheima.net/v1_0/channels')
const channelList = res.data.data
console.log(channelList)
}
完整写法,查看数据是否接收到

渲染列表:
<button @click="ChannelStore.getList">获取频道数据</button>
<ul>
<li v-for="item in ChannelStore.channelList" :key="item.id">{{ item.name }}</li>
</ul>

3.4 storeToRefs()
//错误写法 直接解构 会让数据失去响应式
const {count,msg}=counterStore
//正确写法
import {storeToRefs} from 'pinia'
const {count,msg}=storeToRefs(counterStore)
解释说明:
为什么在 pinia 中,不能直接解构,而要用storeToRefs()?
inia 的 state 是响应式对象(reactive),直接解构会失去响应性
Pinia 的 store 是一个包含了响应式对象的 Proxy,但当你做 const { count } = store,你只是把 .value 拿出来了,相当于“脱壳”了
3.5 数据持久化
使用持久化插件,默认存储在 local storage 中
官方文档:https://prazdevs.github.io/pinia-plugin-persistedstate/zh/
补充知识
localStorage 的生命周期
- 永久存储(除非主动删除)。
- 浏览器关闭、电脑重启都不会消失。
- 只有在下面几种情况才会消失:
- 用户手动清除浏览器缓存/存储。
- 用户用代码调用 localStorage.removeItem(key) 或 localStorage.clear()。
- 浏览器运行在某些“隐身/无痕模式”下,可能在会话结束时清空。
- 👉 所以我们一般说 localStorage 生命周期 = 永久,直到被清除为止。
1.安装插件 pinia-plugin-persistedstate
npm i pinia-plugin-persistedstate
2.main.js 中将持久化插件加入到 pinia 中
import { createPinia } from 'pinia'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
const pinia = createPinia()
pinia.use(piniaPluginPersistedstate)
这里的重点是把piniaPluginPersistedstate加入到pinia中,核心代码是pinia.use(piniaPluginPersistedstate),在已经有 pinia 的情况下
3.配置 store/counter.js
import { defineStore } from 'pinia'
import { ref } from 'vue'
export const useStore = defineStore(
'main',
() => {
const someState = ref('hello pinia')
return { someState }
},
{
persist: true,
},
)
演示:
演示中,只展示开启全部数据永久化和修改存储的数据名称,其他的配置都在官方文档的配置中,如修改部分数据永久化等
开启全部数据永久化
counter.js 代码如下:
//导入定义仓库的包
import { defineStore } from 'pinia'
//导入定义数据的包
import {ref} from 'vue'
//导入computed
import {computed} from 'vue'
//定义 store
//defineStore(仓库唯一标识,()=>{...})
//defineStore返回的是函数,用一个函数名接收,方便后续的使用
export const useCounterStore= defineStore('counter',()=>{
//声明数据 state-count
const count=ref(0)
//声明数据 state-msg
const msg=ref('hello pinia')
//声明数据操作的方法 action
const addCount =()=>{
count.value++
}
const subCount =()=>{
count.value--
}
//声明基于数据派生的计算属性 getters
const double =computed(()=>count.value*2)
return{
count,
msg,
addCount,
subCount,
double,
}
},{
persist: true
}
)

将存储的数据 key 修改:
官方配置文档中:
,{
persist: true
}该写成
,{
persist:
{
key:'mydata'
}
}

更多推荐
所有评论(0)