1.安装
1 2 3
| yarn add pinia # 或者使用 npm npm install pinia
|
在vue项目中,一般会在src下建立/store文件夹,用以存放全局状态文件。
1 2 3 4 5 6 7 8 9 10 11 12 13
| import {createPinia} from "pinia"; const store = createPinia(); export default store;
import store from './store' app.use(store)
import { createPinia } from 'pinia' app.use(createPinia())
|
2.核心概念
1.State
大多数时候,state 是 store 的核心部分。 我们通常从定义应用程序的状态开始。 在 Pinia 中,状态被定义为返回初始状态的函数。 Pinia 在服务器端和客户端都可以工作。(其实也就是全局共享的数据,如登录用户信息)
定义State
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| import { defineStore } from 'pinia' const useStore = defineStore('storeId', { state: () => { return { counter: 0, name: 'Eduardo', isAdmin: true, } }, })
import { defineStore } from 'pinia' const useStore = defineStore('storeId', { state: () => ({ counter: 0, name: 'Eduardo', isAdmin: true, }), })
|
当你在箭头函数中使用大括号 {} 包围代码块时,你必须显式使用 return 语句来指定返回值。这是因为大括号 {} 可以包含多个语句,因此你需要明确指定哪个语句的结果应该作为函数的返回值。
所以,如果你写成 f: () => { return {} },这与 f: () => ({}) 是等价的,都表示函数 f 返回一个空对象。在这种情况下,大括号 {} 包含了一个 return 语句,指定了返回值为空对象。如果你省略大括号,那么箭头函数将默认将后面的表达式作为返回值。
访问State
1 2 3 4 5 6
| import {useStore} from '../store/module/user' const store = useStore()
console.log(store.counter)
store.$reset()
|
注意store类型是一个reactive包裹的响应式对象
为了从 Store 中提取属性同时保持其响应式,您需要使用storeToRefs()或者使用计算属性。 它将为任何响应式属性创建 refs。 当您仅使用 store 中的状态但不调用任何操作时,这很有用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| import { storeToRefs } from 'pinia' export default defineComponent({ setup() { const store = useStore() const { name, doubleCount } = storeToRefs(store) return { name, doubleCount } }, })
|
修改状态
方式1
方式2
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| store.$patch({ counter: store.counter + 1, name: 'Abalam', })
store.$patch((state) => { state.items.push({ name: 'shoes', quantity: 1 }) state.hasChanged = true })
store.$state = { counter: 666, name: 'Paimon' }
|
订阅状态
订阅状态的变化,每当状态被修改或改变时,都会触发回调函数
1 2 3 4 5 6 7 8 9 10
| cartStore.$subscribe((mutation, state) => { mutation.type mutation.storeId mutation.payload localStorage.setItem('cart', JSON.stringify(state)) })
|
2.Getters
Getter 完全等同于 Store 状态的 计算值。 它们可以用 defineStore() 中的 getters 属性定义。 他们接收“状态”作为第一个参数以鼓励箭头函数的使用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| export const useStore = defineStore('main', { state: () => ({ counter: 0, }), getters: { doubleCount(state) { return state.counter * 2 }, doublePlusOne(): number { return this.counter * 2 + 1 }, doubleCountPlusOne():number { return this.doubleCount + 1 }, getUserById: (state) => { return (userId) => state.users.find((user) => user.id === userId) }, getOtherStore(state){ const otherStore = useOtherStore() return state.count + otherStore.count }, }, })
|
可以直接访问Store的任何getter作为store的属性,就和state属性一样
3.Actions
Actions 相当于组件中的 methods。 它们可以使用 defineStore() 中的 actions 属性定义,并且它们非常适合定义业务逻辑:
1 2 3 4 5 6 7 8 9 10 11 12 13
| export const useStore = defineStore('main', { state: () => ({ counter: 0, }), actions: { increment() { this.counter++ }, randomizeCounter() { this.counter = Math.round(100 * Math.random()) }, }, })
|
- 和getters一样,在actions同样可以访问其他Store
- 可以定义异步方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| import { useAuthStore } from './auth-store'
export const useSettingsStore = defineStore('settings', { state: () => ({ }), actions: { async fetchUserPreferences(preferences) { const auth = useAuthStore() if (auth.isAuthenticated) { this.preferences = await fetchPreferences() } else { throw new Error('User must be authenticated') } }, }, })
|
订阅Actions
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| const unsubscribe = someStore.$onAction( ({ name, // action 的名字 store, // store 实例 args, // 调用这个 action 的参数 after, // 在这个 action 执行完毕之后,执行这个函数 onError, // 在这个 action 抛出异常的时候,执行这个函数 }) => { 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()
|