1. 介绍
它是2019 年 11 月对于新版本的vue提供的组合Api进行的尝试,它可以很好的集合vue新的api方法,且还很好的支持ts的写法,Pinia已经被纳入官方代码仓库中,也可以理解为Pinia为最新版本的vuex5。
2. Pinia 和 Vuex
- Vuex:namespaced State、Gettes、Mutations(同步)、Actions(异步)
- Pinia: State、Gettes、Actions(同步异步都支持)
Vuex 当前最新版是 4.x
- Vuex4 用于 Vue3
- Vuex3 用于 Vue2
Pinia 当前最新版是 2.x,它即支持 Vue2 也支持 Vue3。就目前而言 Pinia 是我们在vue3 项目中的首选,尤其是 TypeScript 的项目。
3. 安装和基本使用
安装:
yarn add pinia
使用:
-
在入口文件进行初始化(main.js):
// 创建vue入口程序,由原来的类实例,变成现在的函数方式,为了更好在打包时优化代码 import { createApp } from 'vue' // 根组件 import App from './App.vue' // 路由 import router from './router' import createGlobalComponent from './components' import globalProperties from './config/globalProperties' // pinia import { createPinia } from 'pinia' // pinia配置 const pinia=createPinia() // 工作中常用写法: createApp(App) .use(createGlobalComponent) .use(globalProperties) .use(router) .use(pinia) .mount('#app')
-
创建 pinia 模块(pinia/film.js):
import { defineStore } from 'pinia' // 参数1:命名空间名称 // 参数2:对象,配置 state getters actions const useFilmStore = defineStore('film',{ state:()=>({ num:100 }), actions:{ } }) export default useFilmStore
-
电影页面:
<template> <div> <h3>电影列表 -- {{ store.num }} -- {{num}}</h3> <button @click="addNum">++++</button> </div> </template> <script setup> import { storeToRefs } from 'pinia'; // 状态是完全独立的一个模块 import useFilmStore from '../pinia/film'; const store = useFilmStore() // 使用 storeToRefs 可以解构出来 state 中的属性,而且它还保持响应式 const { num } = storeToRefs(store) // pinia不用通过commit方法更改数据,可以直接在组件中更改数据,并且是响应式的 const addNum = () => { store.num++ } </script> <style lang="scss" scoped> </style>
4. pinia修改数据状态
电影页面:
<template>
<div>
<h3>电影列表 -- {{ store.num }} -- {{ num }}</h3>
<ul>
<li v-for="item of store.arr" :key="item">{{ item }}</li>
</ul>
<button @click="addNum">++++</button>
</div>
</template>
<script setup>
import { storeToRefs } from 'pinia';
// 状态是完全独立的一个模块
import useFilmStore from '../pinia/film';
const store = useFilmStore()
// 使用 storeToRefs 可以解构出来 state 中的属性,而且它还保持响应式
const { num } = storeToRefs(store)
// pinia不用通过commit方法更改数据,可以直接在组件中更改数据,并且是响应式的
const addNum = () => {
// 方案一:直接修改 state 中的数据,这种方式无法进行批处理,如果修改的属性过多,性能不高
// store.num++
// 方案2:批处理,如果一次性修改多个属性建议用$patch来完成,性能更高
// store.$patch({
// num: store.num + 1,
// arr: store.arr.concat(Date.now())
// })
// 方案2回调函数写法:批处理,回调函数写法来批量修改,这样可以防止$patch如果进行了对象合并,批处理数据不完整的情况出现
// store.$patch(state => {
// store.num + 1
// store.arr.push(Date.now())
// })
// 方案3:调用pinia模块下的actions中的方法,完成数据更新
store.addNum(1)
}
</script>
<style lang="scss" scoped>
</style>
pinia/film.js:
import { defineStore } from 'pinia'
// 参数1:命名空间名称
// 参数2:对象,配置 state getters actions
const useFilmStore = defineStore('film', {
state: () => ({
num: 100,
arr: [1, 2, 3]
}),
actions: {
addNum(n) {
// 方案1
// 同步
this.num += n
// 异步
setTimeout(() => {
this.num += n
}, 1000)
// 方案2
this.$patch(state=>{
state.num+=n
state.arr.push(Date.now())
})
},
}
})
export default useFilmStore
5. pinia持久化处理
安装:
yarn add pinia-plugin-persistedstate@2
入口文件中导入:
// pinia中数据持久化
import { persistedState } from 'pinia-plugin-persistedstate'
pinia.use(persistedState)
在pinia模块中使用:
import { defineStore } from 'pinia'
// 参数1:命名空间名称
// 参数2:对象,配置 state getters actions
const useFilmStore = defineStore('film', {
// 当前pinia模块中的所有的数据进行持久化处理
// 默认使用的是 localStorage,且它存储在 localStorage 中的 key 的名称为命名空间名称[id名称]
// persist: true,
// 指定模块中要持久化的数据
persist: {
// 指定要持久化的 state 对象中的属性名称
paths: ['num'],
// 自定义localStorage中的key的名称,一般不修改
key: 'filmstore',
// 自定义使用localStorage还是sessionStorage存储介质
storage: window.sessionStorage
},
state: () => ({
num: 100,
arr: [1, 2, 3]
}),
actions: {
addNum(n) {
// 方案1
// 同步
this.num += n
// 异步
setTimeout(() => {
this.num += n
}, 1000)
// 方案2
this.$patch(state => {
state.num += n
state.arr.push(Date.now())
})
},
}
})
export default useFilmStore
6. 自定义插件
Pinia中文文档:https://pinia.web3doc.top/core-concepts/plugins.html