Vue3 Pinia

多个组件常常需要共享同一份状态,比如登录用户、购物车、主题偏好,若各自维护一份数据就会互相脱节。Pinia 是 Vue3 官方推荐的状态管理库:它把共享状态收进一个个 store,任何组件都能读取与修改,写法比旧版 Vuex 简洁,对 TypeScript 的支持也更好。

安装与接入

先用包管理器安装 pinia:

npm install pinia

再在入口文件 main.js 中注册插件:

import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'

const app = createApp(App)
app.use(createPinia())   // 安装 Pinia
app.mount('#app')

定义 Store

用 defineStore 定义一个计数器 store,含 state、getters、actions:

// stores/counter.js
import { defineStore } from 'pinia'

export const useCounterStore = defineStore('counter', {
  state: () => ({ count: 0 }),        // 状态
  getters: {                          // 派生值,相当于计算属性
    double: (state) => state.count * 2,
  },
  actions: {                          // 修改状态的方法
    increment() {
      this.count++
    },
  },
})

store 的名字 counter 全应用唯一,便于调试工具识别。

在组件中使用

组件中调用 useCounterStore 即可拿到共享 store:

<script setup>
import { useCounterStore } from '../stores/counter'

const store = useCounterStore()
</script>

<template>
  <p>当前计数:{{ store.count }},翻倍:{{ store.double }}</p>
  <button @click="store.increment()">加一</button>
</template>

页面显示「当前计数:0,翻倍:0」,点击后数字同步变化,任何组件看到的都是同一份状态。

解构与保持响应式

直接解构 state 会丢失响应性,需借助 storeToRefs:

<script setup>
import { storeToRefs } from 'pinia'
import { useCounterStore } from '../stores/counter'

const store = useCounterStore()
const { count } = storeToRefs(store)   // 解构后仍保持响应
</script>

<template>
  <p>{{ count }}</p>
</template>

actions 解构则无此顾虑,可直接 const { increment } = store

组合式风格与持久化

Pinia 也支持组合式风格定义,并在 action 中自行持久化:

// stores/user.js
import { ref } from 'vue'
import { defineStore } from 'pinia'

export const useUserStore = defineStore('user', () => {
  const token = ref(localStorage.getItem('token') || '')

  function login(newToken) {
    token.value = newToken
    localStorage.setItem('token', newToken)   // 写入本地存储
  }
  return { token, login }
})

刷新页面后从 localStorage 恢复 token,登录态得以保持。

小结

Pinia 用 defineStore 组织共享状态:state 存数据、getters 做派生、actions 改数据。组件间通过 store 单例读写,配合 storeToRefs 与 localStorage,即可满足绝大多数全局状态需求。

笔记加载中…