一、pinia 特点
- 体积小、性能好、使用简单、限制少
- 支持 Vue Devtools、模块热更新、服务端渲染、Vue2 和 Vue3
- 没有 mutations,只有 state、getters、actions(异步和同步都可)
二、pinia 安装配置
- 安装
npm install pinia -S
- 在 main.js 中注册 pinia
import { createPinia } from 'pinia'
app.use(createPinia())
- 注意事项
1. pinia 的配置是模块化的,通过 defineStore() 函数的参数来定义不同模块,通过 import 导入的方式在组件中使用
2. 根据 defineStore() 的参数不同:可以通过选项式的方式定义模块store、也可以通过组合API的方式定义模块store
3. 在组件中使用 store 中的state数据需要注意:store直接在模板中使用是响应式的,但是如果通过解构的方式使用则不是响应式的,
如果一定要解构使用,可以通过 storeToRefs(store) 函数对 store 进行响应式解构
4. 在 pinia 中改变 state 的状态,可以直接通过赋值的方式进行改变,没有vuex中只能通过commit修改的限制
5. 在组件中使用模块store中 state 的数据时直接使用store.的方式,而不是store.state.,使用 getter 也是一样直接 store.
6. 在组件中使用模块store中 action 方法时直接使用既可,不需要使用模块的名称,
因为我们在组件中使用import解构导入store时,已经指定了模块下的store
7. pinia 中的 getter 没有缓存效果,相当于调用函数,可传入参数
三、pinia 通过选项方式配置 store
- 创建 src\stores\a.js 模块配置文件
import { defineStore } from 'pinia'
export const aStore = defineStore({
id: 'a',
state: () => ({
a: 1,
oa: { a: 100 }
}),
getters: {
ca: (state) => {
return state.a * 2
}
},
actions: {
// actions 同步
SYNCA() {
this.a = this.a * 2
},
// actions 异步
async ASYNCA(params) {
const data = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
params ? resolve(params + 1) : reject(0)
}, 2000)
})
}
const getData = await data()
this.oa.a = this.oa.a * getData
// 如果有部分数据没有在state中定义,但是需要在组件中使用,也可以通过返回 promise 的方式异步处理
// return getData
}
}
})
- 在组件中使用
<template>
<div>
<h1>{{ useAStore.a }}</h1>
<h1>{{ oa.a }}</h1>
<h1>{{ ca }}</h1>
<button @click="setSYNCA">setSYNCA</button>
<button @click="setASYNCA">setASYNCA</button>
</div>
</template>
<script setup>
import { aStore } from '@/stores/a.js'
import { storeToRefs } from 'pinia'
const useAStore = aStore()
const { oa, ca } = storeToRefs(useAStore) // 响应式解构数据
const { SYNCA, ASYNCA } = useAStore
function setSYNCA() {
oa.value.a ++ // 在组件中,直接通过赋值改变 state
SYNCA(1)
}
function setASYNCA() {
ASYNCA(1)
// 如果在 action 中,返回了一个 promise 数据,可以使用链式的方式获取数据
// ASYNCA(1).then((res) => console.log(res)).catch((err) => console.log(err))
}
</script>
四、pinia 通过组合 API 方式配置 store
- 创建 src\stores\a.js 模块配置文件
import { ref, computed, reactive } from 'vue'
import { defineStore } from 'pinia'
export const aStore = defineStore('a', () => {
// state
const a = ref(1)
const oa = reactive({ a: 100 })
// getters
const ca = computed(() => a.value * 2)
// actions 同步
function SYNCA() {
a.value = a.value * 2
}
// actions 异步
async function ASYNCA(params) {
const data = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
params ? resolve(params + 1) : reject(0)
}, 2000)
})
}
const getData = await data()
oa.a = oa.a * getData
// 如果有部分数据没有在state中定义,但是需要在组件中使用,也可以通过返回 promise 的方式异步处理
// return getData
}
return { a, oa, ca, SYNCA, ASYNCA }
})
- 在组件中使用
<template>
<div>
<h1>{{ useAStore.a }}</h1>
<h1>{{ oa }}</h1>
<h1>{{ ca }}</h1>
<button @click="setSYNCA">setSYNCA</button>
<button @click="setASYNCA">setASYNCA</button>
</div>
</template>
<script setup>
import { aStore } from '@/stores/a.js'
import { storeToRefs } from 'pinia'
const useAStore = aStore()
const { oa, ca} = storeToRefs(useAStore) // 响应式解构数据
const { SYNCA, ASYNCA } = useAStore
function setSYNCA() {
oa.value.a ++ // 直接在组件中,通过赋值改变 state
SYNCA(1)
}
function setASYNCA() {
ASYNCA(1)
// 如果在 action 中,返回了一个 promise 数据,可以使用链式的方式获取数据
// ASYNCA(1).then((res) => console.log(res)).catch((err) => console.log(err))
}
</script>
五、pinia 特色 API
- 批量修改 store 中的 state
import { aStore } from '@/stores/a.js'
aStore.$patch((state) => {
state.items.push({ a: 100 })
state.hasChanged = true
})
- 整体替换 store 中的 state
import { aStore } from '@/stores/a.js'
aStore.$state = {
a: 1,
oa: { a: 100 }
}