还不了解 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全局注入;
yarnaddpinia# 或者使用 npmnpminstallpinia如果你的应用使用的 Vue 版本低于 2.7,你还需要安装组合式 API 包:@vue/composition-api
创建一个pinia实例,根store,并将其传递给应用:main.JS
// import './assets/main.css'import{createApp}from'vue'import{createPinia}from'pinia'importAppfrom'./App.vue'constapp=createApp(App)//创建Vue实例constpinia=createPinia();//创建Pinia实例对象app.use(pinia)//Vue实例挂载 piniaapp.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 对象exportconststore变量=defineStore('唯一id',{state:()=>({//定义管理的 属性:值,}),getters:{/* 定义操作state的计算函数 */},actions:{/* 定义对外修改state的操作函数,支持异步 */},})//方式二: 以 Setup 函数,形式定义Pinia store库exportconststore变量=defineStore('唯一id',()=>{//我们可以定义了一些响应式属性和方法: 属性对应state、函数则对应actionsconstgetters=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几乎类似;exportconstuseCounterStore=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状态管理仓库
<scriptsetup>importSon1Comfrom'@/components/Son1Com.vue'//导入组件依赖;import{useCounterStore}from'@/store/counter'//导入对应的store依赖,并暴漏获取对应的state对象,模板则直接访问;constcounterStore=useCounterStore()</script><template><div><h3>App.vue根组件,获取Pinia数据:{{ counterStore.count }}</h3><Son1Com></Son1Com></div></template><stylescoped></style>Son1Com.vue:子组件引入:可以通过:Store对象.属性\函数\getterss属性直接获取对应值;
<scriptsetup>import{useCounterStore}from'@/store/counter'constcounterStore=useCounterStore();</script><template><divclass="son"><button@click="counterStore.addCount">Pinia数据++</button><br/>我是Son1.vue 获取Pinia数据:{{ counterStore.count }}<br/>Pinia getters管理双倍数据 {{ counterStore.doubleCount }}</div></template><stylescoped>.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是一个非常重要的函数,它用于将Piniastore中的状态属性转换为响应式引用;
为什么需要storeToRefs:直接解构store中的状态可能会导致失去响应性,因为解构出来的变量不再是Vue的响应式数据;
<scriptsetup>importSon1Comfrom'@/components/Son1Com.vue'//导入组件依赖;import{useCounterStore}from'@/store/counter'//导入对应的store依赖,并暴漏获取对应的state对象,模板则直接访问;constcounterStore=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><liv-for="item in channelList":key="item.id">{{ item.name }}</li></ul></div></template><stylescoped></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'importAppfrom'./App.vue'// 导入持久化的插件importpersistfrom'pinia-plugin-persistedstate'constapp=createApp(App)//创建Vue实例constpinia=createPinia();//创建Pinia实例对象app.use(pinia.use(persist))//Vue实例挂载 piniaapp.mount('#app')//app支持链式操: app.use(pinia).mount('#app');启用持久化:在每个需要持久化的store中通过persist: true来开启,默认配置使用localStorage存储整个 state
//defineStore 函数第三个配置参数;//默认配置使用localStorage存储整个state, vue3ID作为KeyexportconstuseCounterStore=defineStore('vue3ID',()=>{/* ...省略... */},{persist:true});持久化配置扩展
🆗,上述完成了Pinia数据持久化:持久化至Local storagekey是store库唯一ID,
插件支持很多配置,比如:自定义Key、设置持久化特有属性,
exportconstuseCounterStore=defineStore('vue3ID',()=>{/* ...省略... */},{persist:{key:'divID',// 修改本地存储的唯一标识paths:['count']// 存储的是哪些数据}});代码管理:
本代码已经使用Git进行管理: