Pinia(发音为/piːnjʌ/,如英语中的“peenya”)是最接近piña(西班牙语中的菠萝)的词;
Pinia开始于大概2019年,最初是作为一个实验为Vue重新设计状态管理
,让它用起来像组合式API
(Composition API)。
从那时到现在,最初的设计原则依然是相同的,并且目前同时兼容Vue2、Vue3,也并不要求你使用Composition API;
Pinia本质上依然是一个状态管理的库
,用于跨组件、页面进行状态共享(这点和Vuex、Redux一样);
那么我们不是已经有Vuex了吗?为什么还要用Pinia呢?
用Pinia来替代Vuex
;TypeScript
一起使用时具有可靠的类型推断支持;和Vuex相比,Pinia有很多的优势:
扁平化
的方式来相互使用的;命名空间
的概念,不需要记住它们的复杂关系;使用Pinia之前,我们需要先对其进行安装:
yarn add pinia
# or with npm
npm install pinia
创建一个pinia并且将其传递给应用程序:
import { createPinia } from 'pinia'
const pinia = createPinia()
export default pinia
import pinia from './store'
createApp(App).use(pinia).mount('#app')
什么是Store?
Store有三个核心概念:
state
、getters
、actions
;定义一个Store:
defineStore()
定义的,export const useCounter = defineStore("counter", {
state() {
return {
counter: 0
}
}
})
这个 name,也称为 id,是必要的,Pinia 使用它来将 store 连接到 devtools。
返回的函数统一使用useX作为命名方案,这是约定的规范;
Store在它被使用之前是不会创建的,我们可以通过调用use函数
来使用Store:
<template>
<div class="app">
app.vue
<div class="counter">
counter: {{ counterStore.count }}
div>
div>
template>
<script setup>
import useCounter from './stores/counter'
const counterStore = useCounter()
script>
注意Store获取到后不能被解构,那么会失去响应式:
storeToRefs()
。const counterStore = useCounter()
// 不是响应式
const { count } = counterStore
// 响应式
const { count: count1 } = toRefs(counterStore)
// 响应式
const { count: count2 } = storeToRefs(counterStore)
state 是 store 的核心部分,因为store是用来帮助我们管理状态的。
const useCounter = defineStore("counter", {
state: () => ({
counter: 0
})
})
读取和写入 state:
const counterStore = useCounter()
counterStore.count++
counterStore.name = 'codermy'
重置 State:
const counterStore = useCounter()
counterStore.$reset()
改变State:
$patch
方法;const counterStore = useCounter()
counterStore.$patch({
counter: 100,
name: 'kobe'
})
替换State:
counterStore.$state = {
counter: 1,
name: 'monic'
}
Getters相当于Store的计算属性
:
const useCounter = defineStore("counter", {
state: () => ({
counter: 0
}),
getters: {
doubleCounter: (state) => state.count * 2
}
})
访问当前store的Getters:
const counterStore = useCounter()
counterStore.doubleCounter
Getters中访问自己的其他Getters:
this
来访问到当前store实例的所有其他属性;doublePlusOne: function(state) {
return this.doubleCounter + 1
}
访问其他store的Getters:
message: function(state) {
const userStore = useUser()
return this.fullname + ':' + userStore.nickname
}
Getters也可以返回一个函数,这样就可以接受参数:
const useCounter = defineStore("main", {
state: () => ({
users: [
{id: 111, name: 'kobe', age: 19},
{id: 112, name: 'james', age: 15},
{id: 113, name: 'mike', age: 29},
]
}),
getters: {
getUserById: (state) => {
return userId => {
const user = state.users.find(item => item.id === userId)
return user
}
}
}
})
Actions 相当于组件中的 methods。
actions: {
increment() {
this.counter++
},
}
function add() {
counterStore.increment()
}
和getters一样,在action中可以通过this访问整个store实例的所有操作;
并且Actions中是支持异步操作的,并且我们可以编写异步函数,在函数中使用await;
import { defineStore } from 'pinia'
const useHome = defineStore("home", {
state: () => ({
banners: [],
recommends: []
}),
actions: {
async fetchHomeMultidata() {
const res = await fetch("http://xxx.xxx:8000/home/multidata")
const data = await res.json()
this.banners = data.data.banner.list
this.recommends = data.data.recommend.list
// return new Promise(async (resolve, reject) => {
// const res = await fetch("http://xxx:8000/home/multidata")
// const data = await res.json()
// this.banners = data.data.banner.list
// this.recommends = data.data.recommend.list
// resolve("bbb")
// })
}
}
})
export default useHome
import { useHome } from './stores/home'
const homeStore = useHome()
homeStore.fetchHomeMultidata().then(res => {
console.log(res)
})