定义Store
defineStore("自定义名字", {}) || defineStore("自定义名字", ()=>{})
定义Store,它的第一个参数要求是一个独一无二的名字,第二个参数是其他配置 (选项式 | 组合式)
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', {
// 其他配置 (选项式 | 组合式)...
})
使用Store
创建组合式 Store
export const useCounterStore = defineStore('counter', () => {
const count = ref(0)
const doubleCount = computed(() => count.value * 2)
function increment() { count.value++ }
return { count, doubleCount, increment }
})
组合式使用 Store
<script setup>
import { storeToRefs } from 'pinia'
import { useCounterStore } from '@/stores/counter'
const store = useCounterStore()
// 解构 store 中 state、 getters 只能使用 storeToRefs()。 另外 actions 可以直接结构使用
const { count, doubleCount } = storeToRefs(store)
const { increment } = store
</script>
创建选项式 Store
export const useCounterStore = defineStore('counter', {
state: (): State => ({
count: 66,
name: "hello",
getAddAge: "haihaihai"
}),
getters: {
increment: (state) => state.count * 2,
getNameAndAge(): string {
return this.name + this.getAddAge;
}
},
actions: {
doubleCount() {
return this.count++
}
}
选项式使用 Store
<script setup>
import { storeToRefs } from 'pinia'
import { useCounterStore } from '@/stores/counter'
export default {
name: 'PiniaDemoPage1',
setup () {
const counterStore = useCounterStore()
return { counterStore }
},
methods: {
fetchData() {
this.store.doubleCount()
}
}
}
</script>
<template>
<h1>increment:{{ store.increment }}</h1>
<button @click="fetchData">Fetch Data{{ store.count }}</button>
<h1>This is an home page {{ store?.name }}</h1>
</template>
使用Store并解构
在解构 state
和 getters
需要使用 pinia 中 storeToRefs
来进行解构,否则直接结构会破坏了响应性
,只有actions
可以直接解构,如下:
<script setup>
import { storeToRefs } from 'pinia'
const store = useCounterStore()
// `name` 和 `doubleCount` 是响应式的 ref
// 同时通过插件添加的属性也会被提取为 ref
// 并且会跳过所有的 action 或非响应式 (不是 ref 或 reactive) 的属性
const { name, doubleCount } = storeToRefs(store)
// 作为 action 的 increment 可以直接解构
const { increment } = store
</script>
Setup Store 中
ref()
就是state
computed()
就是getters
function()
就是actions
state
第一. 重置 state $reset()
-
组合式: 您需要创建自己的
$reset()
方法export const useCounterStore = defineStore('counter', () => { const count = ref(0) function $reset() { count.value = 0 } return { count, $reset } })
-
选项式:在
$reset()
内部,会调用state()
函数来创建一个新的状态对象,并用它替换当前状态const store = useStore() // 重置 store.$reset()
第二. 变更 state $patch
(选项式和组合式都可以这样处理)
store.$patch({
count: store.count + 1,
age: 120,
name: 'DIO',
})
store.$patch((state) => {
state.items.push({ name: 'shoes', quantity: 1 })
state.hasChanged = true
})
第三. 替换 state $state
// 这实际上并没有替换
`$state` store.$state = { count: 24 }
// 在它内部调用
`$patch()`: store.$patch({ count: 24 })
第四. 订阅 state $subscribe
counterStore.$subscribe((mutation, state) => {
// import { MutationType } from 'pinia'
mutation.type // 'direct' | 'patch object' | 'patch function'
// 和 cartStore.$id 一样
mutation.storeId // 'cart'
// 只有 mutation.type === 'patch object'的情况下才可用
mutation.payload // 传递给 cartStore.$patch() 的补丁对象。
// state 整个数据
console.log("state", state)
})
第二个参数是 Boolean, 当为 true 时候表示就算组件卸载也会一直监听。如果参数是 false 时候表示组件卸载,监听也会取消监听。
counterStore.$subscribe((mutation, state) => {}, true)
counterStore.$subscribe((mutation, state) => {}, false)
- 组合式:
<script setup>
const counterStore = useCounterStore()
// 订阅器
counterStore.$subscribe(callback, boolean)
</script>
- 选项式:放在 setup() 中
setup() {
const counterStore = useCounterStore()
// 订阅器
counterStore.$subscribe(callback, boolean)
return { store }
},
getter
第一. getter 相当于组件中的 computed
第二. 在选项式中是 getter
, 在组合式中是 computed
, 例子请看上面 使用Store
第三. 其拥有缓存能力,当其内部所依赖的state没变化不会在执行
第四. 向 getter 传递参数,注意:
会导致其将不再被缓存
export const useUserListStore = defineStore('userList', {
getters: {
getUserById: (state) => {
return (userId) => state.users.find((user) => user.id === userId) // 不在拥有缓存能力
},
},
})
第五. 访问其他 store 的 getter
import { useOtherStore } from './other-store'
export const useStore = defineStore('main', {
state: () => ({
// ...
}),
getters: {
otherGetter(state) {
const otherStore = useOtherStore()
return state.localData + otherStore.data
},
},
})
action
第一. 在选项式中是 actions
, 在组合式中是 function
, 例子请看上面 使用Store
第二. actions 可以是异步的
import { mande } from 'mande'
const api = mande('/api/users')
export const useUsers = defineStore('users', {
state: () => ({
userData: null,
// ...
}),
actions: {
async registerUser(login, password) {
try {
this.userData = await api.post({ login, password })
showTooltip(`Welcome back ${this.userData.name}!`)
} catch (error) {
showTooltip(error)
// 让表单组件显示错误
return error
}
},
},
})
第三. 订阅 action $onAction
第二个参数是 Boolean, 当为 true 时候表示就算组件卸载也会一直监听。如果参数是 false 时候表示组件卸载,监听也会取消监听。
someStore.$onAction(callback, Boolean)
- 组合式:
<script setup>
const counterStore = useCounterStore()
// 订阅器
counterStore.$onAction(callback, boolean)
</script>
- 选项式:放在 setup() 中
setup() {
const counterStore = useCounterStore()
// 订阅器
counterStore.$onAction(callback, boolean)
return { store }
},
TypeSctipt
interface State {
userList: UserInfo[]
user: UserInfo | null
}
const useStore = defineStore('storeId', {
state: (): State => {
return {
userList: [],
user: null,
}
}
})