Pinia使用案例

330 阅读4分钟

安装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的优势与缺点

优势:

  1. 轻量级:其体积大约只有1KB,这使得它在项目中引入时不会带来过大的负担。
  2. 简单易用:Pinia的API设计更加简洁和直观,易于理解和使用,使得开发者能够快速上手。
  3. TypeScript支持:Pinia内置了对TypeScript的支持,避免了类型错误的问题。
  4. 模块化:Pinia支持将状态分割成多个模块,每个模块可以独立管理自己的状态。这种设计使得应用状态更加清晰可控,提高了代码的可维护性。
  5. 性能优化:Pinia内部使用了响应式编程的技术,能够提高状态管理的性能和响应速度。只在需要更新时才会触发重新渲染,从而提高了应用程序的性能。
  6. 支持多个Store:与Vuex只支持一个store实例不同,Pinia支持多个store实例,提供了更加灵活的状态管理方式。
  7. 插件生态系统:Pinia提供了丰富的插件生态系统,可以轻松地集成其他工具和库,如Devtools、Persist和Router等。

缺点:

  1. 相对较新:Pinia是一个相对较新的状态管理库,因此它可能存在一些未知的问题和限制。由于它的生态系统可能还不够完善,可能需要花费更多的时间来解决问题。
  2. 不支持某些调试功能:与Vuex相比,Pinia不支持时间旅行和编辑等调试功能,这可能会在某些开发场景下带来不便。
  3. 配置本地存储较麻烦:Pinia默认将状态存储在内存中,如果需要使用本地存储,其配置可能相对于Vuex来说更加复杂和麻烦。