Pinia
Pinia是Vue官方出的存储库,可以在组件或页面间共享数据。Pinia是官方用来取代Vuex库的。相比于Vuex,Pinia更加简洁,而且支持组合式API。
安装
可以通过npm或pnpm进行安装,如下:
pnpm install pinia
然后需要创建一个pinia实例并注册成vue插件,如下:
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
const pinia = createPinia()
const app = createApp(App)
app.use(pinia)
app.mount('#app')
开始使用
下面是一个简单的例子:
// stores/counter.js
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', {
state: () => {
return { count: 0 }
},
getters: {
double: (state) => state.count * 2,
},
actions: {
increment() {
this.count++
},
},
})
这里defineStore的第一个参数是id,也就是name,所以也可以这样写:
export const useCounterStore = defineStore({
id:'counter',
state: () => {
...
},
...
})
使用的时候:
import { useCounterStore } from '@/stores/counter'
export default {
setup() {
const counter = useCounterStore()
counter.count++
// or using an action instead
counter.increment()
},
}
组合式API
上面defineStore也可以使用组合式API,如下:
export const useCounterStore = defineStore('counter', () => {
const count = ref(0)
function increment() {
count.value++
}
return { count, increment }
})
在组合式API中,ref相当于state,computed相当于getters,function相当于actions
响应性
Pinia会默认将store实例包装成reactive,这样保证了响应性。但是如果对store进行解构,为了保持响应性,需要使用storeToRefs(),如下:
<script setup>
import { storeToRefs } from 'pinia'
const store = useStore()
//const { name, doubleCount } = store //这样会失去响应性
const { name, doubleCount } = storeToRefs(store) //保持响应性
</script>
State
上面知道我们可以直接访问和修改state。但是也有另外一种方法,官方为store对象添加几个函数是关于state的,如下:
$reset
将state重制回初始状态
$patch
修改state,主要作用是可以同时修改几个数据,如:
store.$patch({
counter: store.counter + 1,
age: 120,
name: 'DIO',
})
这个函数也可以接受一个function参数,用来处理更复杂的修改,比如为列表添加元素:
cartStore.$patch((state) => {
state.items.push({ name: 'shoes', quantity: 1 })
state.hasChanged = true
})
$state
替换state,上面$patch函数只是修改几个数据,而这个函数则完全替换整个state。
$subscribe
监听state的变化,如下:
cartStore.$subscribe((mutation, state) => {
// import { MutationType } from 'pinia'
mutation.type // 'direct' | 'patch object' | 'patch function'
// same as cartStore.$id
mutation.storeId // 'cart'
// only available with mutation.type === 'patch object'
mutation.payload // patch object passed to cartStore.$patch()
// persist the whole state to the local storage whenever it changes
localStorage.setItem('cart', JSON.stringify(state))
})
Getters
上面提到过,getters等同于computed()。
注意:getters中不能定义与state中同名的元素,否则会报错。
Actions
上面提到过,actions等同于function。
store对象有一个函数$onAction可以用来监听action,如下:
export default {
setup() {
const someStore = useSomeStore()
someStore.$onAction(callback, true)
},
}
组件外使用
在组件外使用要格外注意,比如我们在一个工具类js文件中去使用,如下:
//utils.js
import { useCounterStore } from '@/stores/counter'
const counter = useCounterStore()
这样会报错,应该这时候Pinia还没有创建和装载到APP上,所以const counter = useCounterStore()要放到合适的地方,时机必须是确定Pinia已经创建装载到应用后。