Pinia 中文学习文档

🧩 Pinia 中文学习文档

📘 一、Pinia 简介

✅ 1. Pinia 是什么?

Pinia 是一个 Vue 的状态管理库,可以理解为新版的 Vuex(但更轻量、语法更现代)。

它的作用是:

  • 让组件之间共享数据;
  • 管理全局状态(比如登录信息、主题、购物车等);
  • 持久化(保存状态到 localStorage);
  • 更好的 TypeScript 支持。

📦 二、安装与初始化

1. 安装 Pinia

npm install pinia

2. 在 main.js 中引入

// 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(状态仓库)

Pinia 中的核心概念是 “Store”,相当于一个模块,用来管理一类状态。

示例:定义用户状态

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

export const useUserStore = defineStore('user', {
  // 1️⃣ state - 数据
  state: () => ({
    name: 'Karry',
    age: 25,
    isLogin: false,
  }),

  // 2️⃣ getters - 计算属性(类似于 computed)
  getters: {
    welcomeMessage: (state) => `你好,${state.name}!`,
  },

  // 3️⃣ actions - 方法(可以包含异步操作)
  actions: {
    login(name) {
      this.name = name
      this.isLogin = true
    },
    logout() {
      this.isLogin = false
      this.name = ''
    },
  },
})

🎮 四、在组件中使用 Store

<template>
  <div>
    <h2>{{ userStore.welcomeMessage }}</h2>
    <p>年龄:{{ userStore.age }}</p>

    <button @click="userStore.login('小明')">登录</button>
    <button @click="userStore.logout">退出</button>
  </div>
</template>

<script setup>
import { useUserStore } from '@/stores/user'
const userStore = useUserStore()
</script>

🔍 特点:

  • userStore 是响应式的,可以直接在模板中使用;
  • 调用 actions 就像调用普通方法一样简单。

🧠 五、Store 的核心概念

分类用途特点
state存储数据响应式、可直接修改
getters计算属性类似 computed,自动缓存
actions方法(同步/异步)支持异步请求、业务逻辑

🧩 六、支持异步操作

// src/stores/todo.js
import { defineStore } from 'pinia'

export const useTodoStore = defineStore('todo', {
  state: () => ({
    todos: [],
  }),

  actions: {
    async fetchTodos() {
      const res = await fetch('https://jsonplaceholder.typicode.com/todos?_limit=5')
      this.todos = await res.json()
    },
  },
})

使用:

<template>
  <div>
    <button @click="todoStore.fetchTodos">加载任务</button>
    <ul>
      <li v-for="todo in todoStore.todos" :key="todo.id">{{ todo.title }}</li>
    </ul>
  </div>
</template>

<script setup>
import { useTodoStore } from '@/stores/todo'
const todoStore = useTodoStore()
</script>

💾 七、状态持久化(刷新不丢)

安装插件:

npm install pinia-plugin-persistedstate

在 main.js 中注册:

import { createPinia } from 'pinia'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'

const pinia = createPinia()
pinia.use(piniaPluginPersistedstate)

在 store 中开启:

export const useUserStore = defineStore('user', {
  state: () => ({ name: '', token: '' }),
  persist: true // 👈 自动保存到 localStorage
})

🧰 八、多个 Store 的配合使用

// user.js
export const useUserStore = defineStore('user', {
  state: () => ({ name: 'Karry' })
})

// settings.js
export const useSettingStore = defineStore('settings', {
  state: () => ({ theme: 'dark' }),
  actions: {
    toggleTheme() {
      this.theme = this.theme === 'dark' ? 'light' : 'dark'
    }
  }
})

在组件中:

<script setup>
import { useUserStore } from '@/stores/user'
import { useSettingStore } from '@/stores/settings'

const user = useUserStore()
const settings = useSettingStore()
</script>

🔄 九、重置 Store 状态

有时候需要“清空”状态,比如退出登录:

userStore.$reset()

🧩 十、订阅 Store 的变化(监听状态变化)

userStore.$subscribe((mutation, state) => {
  console.log('变化类型:', mutation.type)
  console.log('新状态:', state)
})

🚀 十一、使用 TypeScript(可选)

Pinia 原生支持 TS:

export const useUserStore = defineStore('user', {
  state: (): { name: string; age: number } => ({
    name: '',
    age: 0,
  }),
})

TypeScript 会自动推导所有类型,非常友好。


🌈 十二、一个完整示例(用户中心)

<template>
  <div class="user-page">
    <h2>👋 {{ userStore.name ? userStore.welcomeMessage : "请登录" }}</h2>

    <div v-if="!userStore.isLogin">
      <input v-model="username" placeholder="请输入用户名" />
      <button @click="userStore.login(username)">登录</button>
    </div>

    <div v-else>
      <button @click="userStore.logout">退出登录</button>
    </div>
  </div>
</template>

<script setup>
import { ref } from "vue";
import { useUserStore } from "@/stores/user";

const username = ref("");
const userStore = useUserStore();
</script>

<style scoped>
.user-page {
  text-align: center;
  padding: 40px;
}
input {
  padding: 8px;
  border-radius: 6px;
  border: 1px solid #ccc;
}
button {
  margin-left: 10px;
  padding: 8px 14px;
  border: none;
  border-radius: 6px;
  background: #409eff;
  color: #fff;
}
</style>

📖 十三、常见问题(FAQ)

问题解决方案
Pinia 与 Vuex 有什么区别?Pinia 更轻量、API 简洁,不需要 mutations,更好用。
能否替代 Vuex?可以,Vue3 官方推荐。
支持 Vue2 吗?支持,需配合 Vue 2.7+ 或 @vue/composition-api。
如何持久化?使用 pinia-plugin-persistedstate 插件。
怎么拆分模块?直接创建多个 Store 文件(每个管理一类状态)。

🧭 十四、推荐学习路线

阶段内容
入门学习 state、getters、actions 的使用
进阶学会模块化、异步请求、持久化
实战将 Pinia 应用于项目(登录、主题、用户信息)
优化学习插件机制、自定义持久化策略

📚 十五、官方文档参考


评论

等风等雨等你来