安装Pinia
yarn add pinia
引入并创建pinia
在main.js中使用createPinia创建pinia。
//main.ts
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import './style.css'
import App from './App.vue'
//创建pinia
const pinia = createPinia()
const app = createApp(App)
//挂载pinia
app.use(pinia)
app.mount('#app')
创建store
使用Pinia的defineStore方法创建store,并定义state、getters、actions等属性。
- State:Pinia中的状态,可以直接读取和写入。相当于组件的data
- Getters:基于state的计算属性,用于封装复杂逻辑。相当于组件的computer
- Actions:用于修改state的函数,可以是同步或异步的。相当于组件的methods
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', {
state: () => {
return {
name:'岚',
count: 0 ,
}
},
getters: {
},
actions: {
addCount() {
this.count = this.count + 2
},
},
})
使用store
在组件中通过useStore函数获取并使用store中的状态和方法。
//vue3+ts
<script setup lang="ts">
import { useCounterStore } from '../store/counter'
defineProps<{ msg: string }>()
const counter = useCounterStore()
</script>
<template>
<h1>{{ msg }}</h1>
<div class="card">
<p>{{ counter.name }}</p>
<button type="button" @click="counter.addCount">count is {{ counter.count }}</button>
</div>
</template>
<style scoped>
</style>
改变数据状态
1.直接在方法中通过操作state.xx来改变
//store
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', {
state: () => {
return {=
count: 0 ,
}
},
})
//组件中
const store = useStore()
store.counter++ // 直接修改counter的值
2.通过$patch可以进行多条数据的修改
使用$patch方法来修改状态,它可以接受一个对象或一个函数作为参数。
- 当传递一个对象时,它将合并到当前状态中。
- 当传递一个函数时,它接收当前状态作为参数,并允许你返回一个新的状态对象。
// 使用对象参数
<script setup lang="ts">
import { useCounterStore } from '../store/counter'
defineProps<{ msg: string }>()
const counter = useCounterStore()
const even = () => {
//使用对象参数
counter.$patch({
name:'山风',
count: counter.count + 1,
})
// 使用函数参数
counter.$patch((state:any):any => {
state.count += 1
state.name = '山风'
})
// 修改数组 注意要在store中声明list
counter.$patch((state) => {
state.list.push({ name: 'shoes', quantity: 1 })
})
}
</script>
<template>
<h1>{{ msg }}</h1>
<div class="card">
<p>{{ counter.name }}</p>
<button type="button" @click="even">count is {{ counter.count }}</button>
<li v-for="(item, index) in counter.list" :key="index">
{{ item.name }}====={{ item.quantity }}
</li>
</div>
</template>
3.通过action改变 在定义的store中,可以使用actions来封装修改状态的逻辑,在组件中引入action去触发
//调用在store中定义的addCount方法来修改count的状态
<button type="button" @click="counter.addCount">count is {{ counter.count }}</button>
4.使用$reset重置,将状态重置为初始值
counter.$reset()
5.直接设置store的$state属性来替换整个状态。
store.$state = {
counter: 666,
// ... 其他属性
}
关于Getter
- 在获取state值之前进行一些逻辑处理
- getter中的值有缓存的特性,若值无改变,多次使用也只会调用一次
- getter中不仅可以使用state.xx的形式改变数据状态,也可以用this去获取数据改变状态(this.msg或state.msg)
一些注意事项
- Pinia中可以在一个sore中引入另一个store
- Pinia可以更好的兼容vue2,vue3和ts,语法上更简洁,变化话的代码编排更符合vue3的Composition Api
- 直接解构store的状态可能会失去响应性,因为Pinia是基于Vue 3的响应性系统工作的。如果需要解构状态,可以使用
storeToRefs来保持响应性 - 尽量避免在组件外部直接修改store的状态,因为这可能会破坏状态管理的封装性和可维护性。最好通过actions来修改状态。
Pinia的优势与缺点
优势:
- 轻量级:其体积大约只有1KB,这使得它在项目中引入时不会带来过大的负担。
- 简单易用:Pinia的API设计更加简洁和直观,易于理解和使用,使得开发者能够快速上手。
- TypeScript支持:Pinia内置了对TypeScript的支持,避免了类型错误的问题。
- 模块化:Pinia支持将状态分割成多个模块,每个模块可以独立管理自己的状态。这种设计使得应用状态更加清晰可控,提高了代码的可维护性。
- 性能优化:Pinia内部使用了响应式编程的技术,能够提高状态管理的性能和响应速度。只在需要更新时才会触发重新渲染,从而提高了应用程序的性能。
- 支持多个Store:与Vuex只支持一个store实例不同,Pinia支持多个store实例,提供了更加灵活的状态管理方式。
- 插件生态系统:Pinia提供了丰富的插件生态系统,可以轻松地集成其他工具和库,如Devtools、Persist和Router等。
缺点:
- 相对较新:Pinia是一个相对较新的状态管理库,因此它可能存在一些未知的问题和限制。由于它的生态系统可能还不够完善,可能需要花费更多的时间来解决问题。
- 不支持某些调试功能:与Vuex相比,Pinia不支持时间旅行和编辑等调试功能,这可能会在某些开发场景下带来不便。
- 配置本地存储较麻烦:Pinia默认将状态存储在内存中,如果需要使用本地存储,其配置可能相对于Vuex来说更加复杂和麻烦。