一、定义一个store
- 安装pinia
yarn add pinia
- 引入pinia
//main.ts
import { createPinia } from 'pinia'
app.use(createPinia())
- 定义一个store
defineStore() 需要一个唯一的名称,作为第一个参数传递
import { defineStore } from 'pinia'
// useStore could be anything like useUser, useCart
// the first argument is a unique id of the store across your application
export const useStore = defineStore('main', {
// other options...
})
- 使用store
import { useCounterStore } from '@/stores/counter'
const store =useCounterStore()
//获取state 方法一
const doubleValue=computed(() => store.doubleCount),
//获取state 结构state 方法二
const { name, doubleCount } = storeToRefs(store)
//修改state数据 方法一
store.counter++
//修改多个数据 方法二
store.$patch({
name:"xxx",
doubleCount+=1
})
//修改多个数据 方法三
store.$patch(state=>{
state.name='xxx'
state.doubleCount+=1
state.arr.push(2)
})
//修改多个数据 方法四
//将操作封装到一个函数里面然后调用即可
store.changeState()
二、核心概念
1.state
定义一个state
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', {
state: () => {
return {
count: 0 as number //可以指定数据类型
}
}, //必须是一个箭头函数否则类型不会推导
// could also be defined as
// state: () => ({ count: 0 })
getters: {
doubleCount: (state) => state.counter * 2,
},
actions: {
increment() {
this.count++
},
},
})
组件内使用state
import { useCounterStore } from '@/stores/counter'
const store =useCounterStore()
//获取state 方法一
const doubleValue=computed(() => store.doubleCount),
//获取state 结构state 方法二
const { name, doubleCount } = storeToRefs(store)
//修改state数据 方法一
store.counter++
//修改多个数据 方法二
store.$patch({
name:"xxx",
doubleCount+=1
})
//修改多个数据 方法三
store.$patch(state=>{
state.name='xxx'
state.doubleCount+=1
state.arr.push(2)
})
//修改多个数据 方法四
//将操作封装到一个函数里面然后调用即可
store.changeState()
//您可以通过调用store 上的方法将状态重置为其初始值:$reset()
store.$reset()
2.getters
接受state参数,鼓励使用箭头函数
定义一个getters
getters: {
//方法一 使用state获取数据
doubleCount: (state) => state.counter * 2,
},
//方法二使用this获取数据,类型推导不出来必须手动指定返回值类型
//如果要访问其他的getters必须使用this这种写法
doublePlusOne(): number {
// autocompletion and typings for the whole store ✨
return this.doubleCount + 1
},
//方法三 支持payload 返回值为一个函数就可以解决payload的问题
getUserById (state) {
return (userId) => state.users.find((user) => user.id === userId)
},
//方法四接受其他store里面的getters
otherGetter(state) {
const otherStore = useOtherStore() //直接使用其他store就可以调用了
return state.localData + otherStore.data
},
组件内使用getters
const doubleCount=computed(()=>{
return store.doubleCount
})
3.action
可以接受一个payload参数
定义一个action
actions: {
//支持自定义参数 payload
increment(num:number) {
this.count+=num
},
//支持使用$patch做批量更新数据
changeState(){
this.$patch(state=>{
state.name='xxx'
state.doubleCount+=1
state.arr.push(2)
})
},
//使用其他容器的actions
async fetchUserPreferences() {
const auth = useAuthStore() //直接把其他容器加载进来使用就可以了
if (auth.isAuthenticated) {
this.preferences = await fetchPreferences()
} else {
throw new Error('User must be authenticated')
}
},
},
组件内使用action
store.increment(10)
store.changeState()
三、函数式写法
export const useCounterStore = defineStore('counter', () => {
const count = ref(0)
function increment() {
count.value++
}
return { count, increment }
})
四、插件
Pinia 插件是一个函数,可以选择返回要添加到商店的属性。它需要一个可选参数,一个context:
import { createPinia } from 'pinia'
// add a property named `secret` to every store that is created after this plugin is installed
// this could be in a different file
function SecretPiniaPlugin() {
return { secret: 'the cake is a lie' }
}
const pinia = createPinia()
// give the plugin to pinia
pinia.use(SecretPiniaPlugin)
// in another file
const store = useStore()
store.secret // 'the cake is a lie'
五、与vuex的区别
- mutations no longer exist. They were very often perceived as extremely verbose. They initially brought devtools integration but that is no longer an issue. //没有mutation
- No need to create custom complex wrappers to support TypeScript, everything is typed and the API is designed in a way to leverage TS type inference as much as possible. //很好的支持typescript
No more magic strings to inject, import the functions, call them, enjoy autocompletion! - No need to dynamically add stores, they are all dynamic by default and you won’t even notice. Note you can still manually use a store to register it whenever you want but because it is automatic you don’t need to worry about it.
- No more nested structuring of modules. You can still nest stores implicitly by importing and using a store inside another but Pinia offers a flat structuring by design while still enabling ways of cross composition among stores. You can even have circular dependencies of stores. //没有module了
- No namespaced modules. Given the flat architecture of stores, “namespacing” stores is inherent to how they are defined and you could say all stores are namespaced. //没有命名空间