介绍
一个拥有组合式 API 的 Vue 状态管理库 主要是面向 Vue 3 的用户,除了安装和 SSR 两章之外,其余章节中提到的 API 均支持 Vue 2 和 Vue Devtools 支持,追踪 actions、mutations 的时间线,在组件中展示它们所用到的 Store,让调试更容易的 Time travel 热更新。不必重载页面即可修改 Store,开发时可保持当前的 State 插件:可通过插件扩展 Pinia 功能 为 JS 开发者提供适当的 TypeScript 支持以及自动补全功能。 支持服务端渲染
对比 Vuex
与 Vuex 相比,Pinia 提供了一个更简单的 API,mutation 已被弃用 提供了符合组合式 API 风格的 API,也可使用选项式API 搭配 TypeScript 一起使用时有非常可靠的类型推断支持 Pinia 从设计上提供的是一个扁平的结构,不再有嵌套结构的模块,不再有可命名的modules。但可以通过导入和使用另一个 Store 来隐含地嵌套 stores 空间。
使用
yarn add pinia
npm install pinia
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
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' )
定义store文件
在store文件夹下新建user.js defineStore定义一个store 第一个参数是你的应用中 Store 的唯一 ID 第二个参数可接受两类值:Setup 函数或 Option 对象 仓库最好使用 store 的名字,同时以 use
开头且以 Store
结尾。(比如 useUserStore
,useCartStore
,useProductStore
)
import { defineStore } from 'pinia'
export const useUserStore = defineStore ( 'user' , {
} )
Option Store 类似选项式API
export const useUserStore = defineStore ( 'User' , { state : ( ) => { return { count : 0 , } } , getters : { doubleCount : ( state ) => state. count * 2 , doubleCountPlus ( ) { return this . doubleCount + 1 } , } , actions : { increment ( ) { this . count++ } , } ,
} )
Setup Store 类似组合式API 的 setup 函数
export const useCounterStore = defineStore ( 'counter' , ( ) => { const count = ref ( 0 ) function increment ( ) { count. value++ } return { count, increment }
} )
使用 Store
store 是一个用 reactive 包装的对象,所以使用方式和reactive对象一样
< script setup>
import { useUserStore } from '@/store/user'
const userStore= useUserStore ( )
let count = userStore. count
import { storeToRefs } from 'pinia'
const { name, doubleCount } = storeToRefs ( userStore)
userStore. increment ( )
const { increment } = userStore
increment ( )
< / script>
修改state的三种方法
直接在页面组件中改变数据 使用$patch改变数据 patch object:是通过我们熟悉的 $patch 的 对象方式 来变化 patch function:也是通过 $patch,但是是通过 函数的方式 来变化 direct:通过 action 变化 重置数据
< template> < div> baseUrl:{ { baseUrl } } < / div> < div> ipList:{ { ipList } } < / div> < button @click= "changeData" > 直接在页面组件中改变数据< / button> < button @click= "changeDataByPatch" > 使用$patch改变数据< / button> < button @click= "changeDataByAction" > 使用action改变数据< / button> < button @click= "resetData" > 重置数据< / button>
< / template> < script setup>
import useAppStore from "@/store/modules/app"
import { storeToRefs } from "pinia"
const store = useAppStore ( )
let { baseUrl, ipList } = storeToRefs ( store)
function changeData ( ) { store. baseUrl = 'https://www.taobao.com/' store. ipList. push ( '192.168.10.111' )
}
function changeDataByPatch ( ) { store. $patch ( { baseUrl : 'https://www.jd.com/' , ipList : [ '192.168.10.777' , '192.168.10.222' , '192.168.10.888' ] } ) store. $patch ( ( state ) => { state. baseUrl = 'https://www.jd.com/' state. ipList[ 1 ] = '192.168.10.222' } )
}
function changeDataByAction ( ) { store. changeState ( 'https://www.alibabagroup.com/cn/global/home' )
}
function resetData ( ) { store. $reset ( )
} < / script>
订阅$subscribe:监听 state 里面的值是否发生了变化
cartStore. $subscribe ( ( mutation, state ) => { console. log ( mutation, state) localStorage. setItem ( 'cart' , JSON . stringify ( state) )
} )
cartStore. $subscribe ( callback, { detached : true } )
当前 getter 访问其他 store 的 getter
import { useOtherStore } from './other-store'
export const useStore = defineStore ( 'main' , { getters : { otherGetter ( state ) { const otherStore = useOtherStore ( ) return state. localData + otherStore. data} , } ,
} )
订阅 action
const unsubscribe = someStore. $onAction ( ( { name, store, args, after, onError, } ) => { const startTime = Date. now ( ) console. log ( ` Start " ${ name} " with params [ ${ args. join ( ', ' ) } ]. ` ) after ( ( result ) => { console. log ( ` Finished " ${ name} " after ${ Date. now ( ) - startTime} ms.\nResult: ${ result} . ` ) } ) onError ( ( error ) => { console. warn ( ` Failed " ${ name} " after ${ Date. now ( ) - startTime} ms.\nError: ${ error} . ` ) } ) }
)
unsubscribe ( )
someStore. $onAction ( callback, true )