这是一份 Pinia
状态管理库的备忘单,列出了 Pinia 的常用命令和操作。
npm install pinia
# or
yarn add pinia
# or
pnpm add pinia
创建一个 store 文件(例如 src/stores/counter.js
),并定义 store
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', {
state: () => ({
count: 0
}),
actions: {
increment() {
this.count++
}
},
getters: {
doubleCount: (state) => state.count * 2
}
})
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
const app = createApp(App)
const pinia = createPinia()
app.use(pinia)
app.mount('#app')
在你的 Vue 应用中创建一个 Pinia 实例并将其传递给 Vue
使用 Vite 时,你可以启用热重载功能:
if (import.meta.hot) {
import.meta.hot.accept(acceptHMRUpdate(useCounterStore, import.meta.hot))
}
在组件中使用 store
<template>
<div>
<p>Count: {{ counterStore.count }}</p>
<p>Double Count: {{ counterStore.doubleCount }}</p>
<button @click="counterStore.increment">Increment</button>
</div>
</template>
<script>
import { useCounterStore } from '@/stores/counter'
export default {
setup() {
const counterStore = useCounterStore()
return {
counterStore
}
}
}
</script>
Pinia 不使用传统的 Vuex 模块模式。相反,推荐使用独立的 store 文件:
// src/stores/user.js
import { defineStore } from 'pinia'
export const useUserStore = defineStore('user', {
state: () => ({
name: 'Alice',
age: 25
}),
actions: {
setName(name) {
this.name = name
}
},
getters: {
isAdult: (state) => state.age >= 18
}
})
如果你更喜欢 Options API,可以这样使用 Pinia:
<script>
import { defineComponent } from 'vue'
import { useCounterStore } from '@/stores/counter'
export default defineComponent({
setup() {
const counterStore = useCounterStore()
return {
counterStore
}
}
})
</script>
你可以将 store 与组合函数一起使用:
// src/composables/useCounter.js
import { useCounterStore } from '@/stores/counter'
export function useCounter() {
const counterStore = useCounterStore()
return {
count: counterStore.count,
doubleCount: counterStore.doubleCount,
increment: counterStore.increment
}
}
Pinia 支持插件。你可以编写插件来扩展 Pinia 的功能:
// src/plugins/piniaPlugin.js
export function piniaPlugin({ store }) {
store.$onAction(({ name, store, args, after, onError }) => {
console.log(`Action ${name} was called with args:`, args)
})
}
// main.js
import { createPinia } from 'pinia'
import { piniaPlugin } from './plugins/piniaPlugin'
const pinia = createPinia()
pinia.use(piniaPlugin)
npm pinia-plugin-persist
在你的入口文件中配置 Pinia 和 pinia-plugin-persist
。
import Vue from 'vue'
import vueCompositionApi from '@vue/composition-api'
import { createPinia, PiniaVuePlugin } from 'pinia'
import piniaPersist from 'pinia-plugin-persist'
import App from './App.vue'
Vue.use(vueCompositionApi)
Vue.use(PiniaVuePlugin)
const pinia = createPinia()
pinia.use(piniaPersist)
new Vue({
pinia,
render: h => h(App)
}).$mount('#app')
Vue 3 项目:
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import piniaPersist from 'pinia-plugin-persist'
import App from './App.vue'
const pinia = createPinia()
pinia.use(piniaPersist)
createApp(App)
.use(pinia)
.mount('#app')
创建一个 Pinia store,并启用持久化存储。
// stores/userStore.js
import { defineStore } from 'pinia'
export const useUserStore = defineStore('userStore', {
state: () => ({
firstName: 'S',
lastName: 'L',
accessToken: 'xxxxxxxxxxxxx'
}),
actions: {
setToken(value) {
this.accessToken = value
}
},
persist: {
enabled: true,
strategies: [
{
storage: localStorage,
paths: ['accessToken']
}
]
}
})
在组件中使用创建好的 store。
// src/components/SomeComponent.vue
<template>
<div>
<p>{{ userStore.firstName }} {{ userStore.lastName }}</p>
<p>{{ userStore.accessToken }}</p>
</div>
</template>
<script>
import { useUserStore } from '@/stores/userStore'
export default {
setup() {
const userStore = useUserStore()
return { userStore }
}
}
</script>
Pinia 支持服务端渲染 (SSR)。在你的 SSR 入口文件中创建 Pinia 实例:
import { createPinia } from 'pinia'
export function createApp() {
const app = createSSRApp(App)
const pinia = createPinia()
app.use(pinia)
return { app, pinia }
}
明白了,让我们来结合 pinia-plugin-persist
插件完善 Pinia 备忘清单。
Pinia 可以与 Vue Devtools 一起使用。确保你安装了最新版本的 Vue Devtools,然后你可以在 Devtools 中查看和调试你的 Pinia store。
Pinia 支持在 actions 中使用异步代码:
// src/stores/todo.js
import { defineStore } from 'pinia'
import axios from 'axios'
export const useTodoStore = defineStore('todo', {
state: () => ({
todos: []
}),
actions: {
async fetchTodos() {
const response = await axios.get('/api/todos')
this.todos = response.data
}
}
})
你可以使用 Vue Test Utils 和 Jest 来测试你的 Pinia store:
// __tests__/counterStore.test.js
import { setActivePinia, createPinia } from 'pinia'
import { useCounterStore } from '@/stores/counter'
describe('Counter Store', () => {
beforeEach(() => {
setActivePinia(createPinia())
})
it('increments the count', () => {
const counterStore = useCounterStore()
expect(counterStore.count).toBe(0)
counterStore.increment()
expect(counterStore.count).toBe(1)
})
it('returns double count', () => {
const counterStore = useCounterStore()
counterStore.count = 2
expect(counterStore.doubleCount).toBe(4)
})
})