目录

重生之我在学Vue-第6天-Vue-3-状态管理Pinia

重生之我在学Vue–第6天 Vue 3 状态管理(Pinia)

重生之我在学Vue–第6天 Vue 3 状态管理(Pinia)

前言

当项目发展到多组件共享状态时,单纯依靠父子组件通信会变得难以维护。Pinia 作为 Vue 3 官方推荐的状态管理工具,提供更清晰的逻辑分层和响应式状态管理。今天我们将学习如何用 Pinia 实现全局状态管理,并构建可维护的任务管理模块。

Vue3 官方中文文档传送点:

Vue3 的中文官方文档学习笔记很全还有练习场,推荐去官网学习

Vue前端成仙之路:

GO后端成神之路:


一、Pinia 核心概念速览

1.1 为什么需要状态管理?

当遇到以下场景时,需引入状态管理:

  • 多个组件依赖同一状态(如用户登录信息)
  • 跨层级组件需要修改同一状态
  • 需要跟踪复杂的状态变更历史

1.2 Pinia 核心三要素

概念作用示例场景
State存储全局响应式数据tasks: [] 任务列表
Getters基于 State 的派生数据(计算属性)completedTasksCount
Actions修改 State 的业务逻辑addTask() , deleteTask()

二、Pinia 快速上手

2.1 安装与初始化

bash

npm install pinia

javascript

// main.js
import { createPinia } from 'pinia'

const app = createApp(App)
app.use(createPinia())
app.mount('#app')

2.2 创建第一个 Store

javascript

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

export const useTaskStore = defineStore('task', {
  state: () => ({
    tasks: [],
    filter: 'all' // all/completed/active
  }),
  getters: {
    filteredTasks() {
      return this.tasks.filter(task => {
        if (this.filter === 'completed') return task.completed
        if (this.filter === 'active') return !task.completed
        return true
      })
    }
  },
  actions: {
    addTask(title) {
      this.tasks.push({
        id: Date.now(),
        title,
        completed: false
      })
    },
    toggleTask(id) {
      const task = this.tasks.find(t => t.id === id)
      if (task) task.completed = !task.completed
    }
  }
})

三、模块化状态管理

3.1 多 Store 场景

bash

src/
  stores/
    taskStore.js    # 任务管理模块
    userStore.js    # 用户模块
    configStore.js  # 系统配置模块

3.2 Store 间通信

javascript

// stores/userStore.js
export const useUserStore = defineStore('user', {
  actions: {
    logout() {
      const taskStore = useTaskStore()
      taskStore.$reset() // 退出时清空任务状态
    }
  }
})

四、在组件中使用 Pinia

4.1 状态访问与修改

vue

<script setup>
import { useTaskStore } from '@/stores/taskStore'

const taskStore = useTaskStore()

// 直接访问状态
console.log(taskStore.tasks) 

// 调用 Action
const handleAdd = () => taskStore.addTask(newTask.value)
</script>

<template>
  <div v-for="task in taskStore.filteredTasks" :key="task.id">
    {{ task.title }}
    <button @click="taskStore.toggleTask(task.id)">切换状态</button>
  </div>
</template>

4.2 状态解构的陷阱

javascript

// ❌ 错误:破坏响应性
const { tasks } = storeToRefs(taskStore) 

// ✅ 正确方式
import { storeToRefs } from 'pinia'
const { tasks } = storeToRefs(taskStore)

五、进阶开发技巧

5.1 持久化存储插件

bash

npm install pinia-plugin-persistedstate

javascript

// main.js
import { createPinia } from 'pinia'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'

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

javascript

// 在 Store 中启用
export const useTaskStore = defineStore('task', {
  persist: true, // 开启持久化
  state: () => ({ /* ... */ })
})

5.2 状态重置与订阅

javascript

// 重置单个 Store
taskStore.$reset()

// 订阅状态变化
taskStore.$subscribe((mutation, state) => {
  console.log('状态变化:', mutation.type, state)
})

六、常见问题解答

Q1:Pinia 和 Vuex 有什么区别?

特性PiniaVuex
Vue 3 支持原生支持需要兼容版本
TypeScript完美支持需要额外配置
代码结构更简洁的 Composition API基于 Options API
模块化天然多 Store 设计需要分 modules

Q2:如何调试 Pinia 状态?

  1. 安装 Vue Devtools
  2. 在浏览器开发者工具中查看 Pinia 标签页
  3. 实时查看状态变化和时间旅行调试

今日任务:构建任务管理模块

  1. 创建 taskStore 实现以下功能:

    • 任务增删改查
    • 按状态过滤任务
    • s任务统计(总数/完成数)
  2. 在组件中集成:

    vue

    <template>
      <div>
        <input v-model="newTask" @keyup.enter="addTask">
        <select v-model="taskStore.filter">
          <option value="all">全部</option>
          <option value="completed">已完成</option>
          <option value="active">未完成</option>
        </select>
        <div v-for="task in taskStore.filteredTasks" :key="task.id">
          {{ task.title }}
          <button @click="taskStore.toggleTask(task.id)">
            {{ task.completed ? '✅' : '⬜' }}
          </button>
        </div>
      </div>
    </template>