还不了解 Pinia 状态管理库⁉️🍍
什么是Pinia❓状态管理工具⁉️: 学习过Vue2
的小伙伴,一定都知道Vuex
,什么不知道,请看VCR👉 ;
Vuex 是一个专为 Vue.js 应用程序设计的状态管理库
,它提供了一种集中式管理
应用中的状态;
-
集中式存储: 它将应用的所有组件
状态(数据)
,集中到一个单一的存储对象中,使得统一管理; -
状态管理模式: 它让组件的
状态(数据)
,管理变得集中、有序,便于在整个应用中,共享和维护数据;
而,在Vue3 为了:遵循组合式API的理念: Pinia官网: 腾空出世☁️,当然其实它也支持Vue2
使迁移新项目选择更灵活;
有人又说了,经典白学,其实完全不用但心❤️,Pinia 支持:Vue2
、Vue3
内部语法,也可以是和Vuex
几乎一模一样;
-
组合式 API: 它与Vue的组合式API无缝对接,使得状态管理更加直观和高效;
-
无需Mutation: 不同于
Vuex
要求通过mutations
改变状态,Pinia
允许直接在actions
中操作state
,并支持异步; -
强大的插件系统: 允许通过插件扩展功能,增强
Pinia
的灵活性和功能性,内置多种配置:数据持久化、state管理; -
TypeScript 支持:提供了更好的
TypeScript
支持,包括自动补全和类型推导,便于开发和维护;
vue-pinia Demo搭建:
Vue3—手动添加Pinia: Vue3、Vite支持自动配置,不过学习阶段还是,尝试一下手动安装:
🆗,veu create @latest
成功创建:vue-pinia
项目;删除无用代码配置、定义Demo模板:
- 需求:App主页面、内引用子组件: 共同获取操作
pinia
数据,按钮调用修改pinia
数据;
Pinia 安装\使用:
Pinia 安装: 官方文档其实都介绍的很详细了,首先下载依赖、main.js
配置,导入Pinia全局注入;
yarn add pinia
# 或者使用 npm
npm install pinia
如果你的应用使用的 Vue 版本低于 2.7,你还需要安装组合式 API 包:@vue/composition-api
创建一个 pinia
实例,根 store
,并将其传递给应用: main.JS
// import './assets/main.css'
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
const app = createApp(App) //创建Vue实例
const pinia = createPinia(); //创建Pinia实例对象
app.use(pinia) //Vue实例挂载 pinia
app.mount('#app')
//app支持链式操: app.use(pinia).mount('#app');
Pinia 核心概念\使用:
和Vuex 一样要使用Pinia,首先要定义: store
库,
每个 store
可以看作是一个独立的数据管理模块,负责特定部分的数据处理和状态维护;Pinia支持两种方式:
- 首先:
Store
是用defineStore(?,?);
定义的,有两个必须参数; defineStore(仓库的唯一标识, ?\?)
,第一个参数要求是一个独一无二的名字;- 第二个参数可接受两类值:Setup函数或 Option对象,分别对应:组合式API、选项式写法;
//引入 pinia 依赖
import { defineStore } from 'pinia'
import { computed, ref } from 'vue'
//方式一: 以 Option对象,形式定义Pinia store库,貌似现在用的比较多,因为结构相对清晰,语法与Vux几乎类似;
//我们也可以传入一个带有 state、actions 与 getters 属性的 Option 对象
export const store变量 = defineStore('唯一id', {
state: () => ({
//定义管理的 属性:值,
}),
getters: { /* 定义操作state的计算函数 */ },
actions: { /* 定义对外修改state的操作函数,支持异步 */ },
})
//方式二: 以 Setup 函数,形式定义Pinia store库
export const store变量 = defineStore('唯一id', () => {
//我们可以定义了一些响应式属性和方法: 属性对应state、函数则对应actions
const getters = computed(()=>{ /* 定义操作state的计算函数 */ })
return { /* 保留外界需要使用的属性\函数 */ }
})
定义 Store:
为了方便管理在Demo中创建: store/counter.js
定义Store
状态管理仓库
import { defineStore } from 'pinia'
import { computed, ref } from 'vue'
// 定义store
// defineStore(仓库的唯一标识, () => { ... })
// 仓库唯一标识,也被称作id:是必须传入的,Pinia将用它来获取store
// defineStore() 的第二个参数可接受两类值:Setup 函数或 Option对象,分别对应Vue3\Vue2写法;
//以 Option对象,形式定义Pinia store库,貌似现在用的比较多,因为结构相对清晰,语法与Vux几乎类似;
export const useCounterStore = defineStore('vue2ID', {
//参数,以对象形式进行传递,内部几乎就是Vuex写法,没有了 mutations 全由actions 定义函数,支持异步)
state: () => ({ count: 0 }),
actions: { addCount() { this.count++ }, },
getters: { doubleCount: (state) => state.count * 2, },
})
//以 Setup 函数,形式定义Pinia store库
// export const useCounterStore = defineStore('vue3ID', () => {
// // 声明数据 count
// const count = ref(100)
// // 声明操作数据的方法 addCount
// const addCount = () => count.value++
// // 声明数据派生计算属性 double 获取双倍count
// const doubleCount = computed(() => count.value * 2) //最后,将需要保留的函数\属性抛出;
// return {
// count,
// addCount,
// doubleCount,
// }
// })
模板引入操作Pinia:
App.vue: 主页面,引入Store
状态管理仓库
<script setup>
import Son1Com from '@/components/Son1Com.vue' //导入组件依赖;
import { useCounterStore } from '@/store/counter'
//导入对应的store依赖,并暴漏获取对应的state对象,模板则直接访问;
const counterStore = useCounterStore()
</script>
<template>
<div>
<h3>App.vue根组件,获取Pinia数据:{{ counterStore.count }}</h3>
<Son1Com></Son1Com>
</div>
</template>
<style scoped></style>
Son1Com.vue: 子组件引入:可以通过:Store对象.属性\函数\getterss属性
直接获取对应值;
<script setup>
import { useCounterStore } from '@/store/counter'
const counterStore = useCounterStore();
</script>
<template>
<div class="son" >
<button @click="counterStore.addCount" >Pinia数据++</button> <br/>
我是Son1.vue 获取Pinia数据:{{ counterStore.count }} <br/>
Pinia getters管理双倍数据 {{ counterStore.doubleCount }}
</div>
</template>
<style scoped>.son { border: 1px solid #000; padding: 30px; }</style>
Pinia action 异步写法:
在 Pinia 中,函数处理主要通过 actions 来实现:
actions
支持同步和异步操作,这对于执行API
调用、延迟操作或任何需要等待的操作非常有用;
需求:使用Pinia 管理一个接口异步数据,给所有模块使用管理,接口: GET: http://geek.itheima.net/v1_0/channels
storeToRefs 函数:
Pinia进行状态管理时: storeToRefs
是一个非常重要的函数,它用于将Pinia
store
中的状态属性转换为响应式引用;
为什么需要storeToRefs: 直接解构store
中的状态可能会导致失去响应性,因为解构出来的变量不再是Vue的响应式数据;
<script setup>
import Son1Com from '@/components/Son1Com.vue' //导入组件依赖;
import { useCounterStore } from '@/store/counter' //导入对应的store依赖,并暴漏获取对应的state对象,模板则直接访问;
const counterStore = useCounterStore()
//实际开发中我们每次都要:store对象.属性\函数太麻烦,能不能解构赋值:直接获取内部属性呢?
//counterStore 不能直接解构,直接解构 store对象 获取属性\函数会丢失响应式;
//const { count,getList,channelList } = counterStore;
//需要通过storeToRefs(store对象)
//将 store对象 状态转换为响应式引用,然后通过解构赋值给局部变量;
const { getList } = counterStore;
import { storeToRefs } from 'pinia';
const { count,channelList } = storeToRefs(counterStore);
</script>
<template>
<div>
<h3>App.vue根组件,获取Pinia数据:{{ count }}</h3>
<Son1Com></Son1Com>
<button @click="getList">获取频道数据</button>
<ul>
<li v-for="item in channelList" :key="item.id">{{ item.name }}</li>
</ul>
</div>
</template>
<style scoped></style>
Pinia 持久化🍍💾
Pinia 提供了数据持久化的能力: 这对于需要在页面刷新后保持状态的应用来说至关重要,为什么需要数据持久化:
- 保持用户状态:例如,用户登录信息、购物车内容等,刷新页面后不应丢失。
- 提升用户体验:用户不需要每次刷新页面都重新设置或登录
使用 pinia-plugin-persistedstate 插件: 支持通过包管理器安装 pinia-plugin-persistedstate
或使用:yarn add pinia-plugin-persistedstate
、npm i pinia-plugin-persistedstate
配置 Pinia: 需要在你的 Pinia 配置文件中引入并使用该插件,即:main.JS
// import './assets/main.css'
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
// 导入持久化的插件
import persist from 'pinia-plugin-persistedstate'
const app = createApp(App) //创建Vue实例
const pinia = createPinia(); //创建Pinia实例对象
app.use(pinia.use(persist)) //Vue实例挂载 pinia
app.mount('#app')
//app支持链式操: app.use(pinia).mount('#app');
启用持久化:在每个需要持久化的 store
中通过 persist: true
来开启,默认配置使用localStorage存储整个 state
//defineStore 函数第三个配置参数;
//默认配置使用localStorage存储整个state, vue3ID作为Key
export const useCounterStore = defineStore('vue3ID', () => { /* ...省略... */ },{ persist: true });
持久化配置扩展
🆗,上述完成了Pinia数据持久化: 持久化至Local storage
key是store库唯一ID,
插件支持很多配置,比如: 自定义Key、设置持久化特有属性,
export const useCounterStore = defineStore('vue3ID', () => { /* ...省略... */ },{
persist: {
key: 'divID', // 修改本地存储的唯一标识
paths: ['count'] // 存储的是哪些数据
}
});
代码管理:
本代码已经使用Git进行管理: 公众号回复:Vue3