vue中新的状态管理器-pinia

背景

对于pinia的使用,可参考官方文档在这不做过多赘述。这边主要来讲讲pinia中 少用且好用的方法,为什么我们选择pinia而不用vuex

ps: 以下写法全部基于组合式API

使用方式:

先下载依赖

  npm i pinia -s

在vue3中,main.js这么写

  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')

ps:就别考虑v2了吧,v2老老实实用vuex。

State

1、如何修改State

在传统的vuex中我们是不建议直接修改state的,而是要求我们通过mutation来修改state,但是在pinia中我们可以直接修改state。例如:

const store = useStore()

store.count++

如果我们需要在同一时间变更多个属性,可以通过$patch方法,例如:

store.$patch((state) => {
  state.items.push({ name: 'shoes', quantity: 1 })
  state.hasChanged = true
})

2、如何订阅State

用来监听state是否发生变化,与watch相比,使用 $subscribe() 的好处是 subscriptions 在 patch 后只触发一次 。例如

cartStore.$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 持久化到本地存储。
  localStorage.setItem('cart', JSON.stringify(state))
})

在组合式API中可以这么使用:

<script setup>
const someStore = useSomeStore()
// this subscription will be kept even after the component is unmounted
someStore.$subscribe(callback, { detached: true })
</script>

Getter

1、如何访问其他store 的 getter

想要使用另一个 store 的 getter 的话,那就直接在 getter 内使用就好,例如:

import { useOtherStore } from './other-store'

export const useStore = defineStore('main', {
  state: () => ({
    // ...
  }),
  getters: {
    otherGetter(state) {
      const otherStore = useOtherStore()
      return state.localData + otherStore.data //otherStore.data 就是其他getter中的getter
    },
  },
})

2、如何像getter中传递参数

Getter 只是幕后的计算属性,所以不可以向它们传递任何参数。不过,你可以从 getter 返回一个函数,该函数可以接受任意参数,例如

export const useStore = defineStore('main', {
  getters: {
    getUserById: (state) => {
      return (userId) => state.users.find((user) => user.id === userId)
    },
  },
})

组件中使用:

<script setup>
import { useUserListStore } from './store'
const userList = useUserListStore()
const { getUserById } = storeToRefs(userList)
// note you will have to use `getUserById.value` to access
// the function within the <script setup>
</script>

<template>
  <p>User 2: {{ getUserById(2) }}</p>
</template>

ps: getter 将不再被缓存,它们只是一个被你调用的函数。不过,你可以在 getter 本身中缓存一些结果,虽然这种做法并不常见,但有证明表明它的性能会更好

Action

1、如何访问其他 store 的 action

举个