Pinia介绍及Vue3配置示例

文章目录

      • [一、Pinia 核心介绍](#一、Pinia 核心介绍)
        • [1. 核心优势](#1. 核心优势)
        • [2. 核心概念](#2. 核心概念)
      • [二、Vue 3 中配置 Pinia](#二、Vue 3 中配置 Pinia)
        • [1. 安装](#1. 安装)
        • [2. 全局注册(main.ts/main.js)](#2. 全局注册(main.ts/main.js))
      • [三、Store 定义(两种风格)](#三、Store 定义(两种风格))
        • [方式 1:选项式(Options API,兼容 Vue 2)](#方式 1:选项式(Options API,兼容 Vue 2))
        • [方式 2:组合式(Composition API,Vue 3 推荐)](#方式 2:组合式(Composition API,Vue 3 推荐))
      • [四、组件中使用(<script setup>)](#四、组件中使用(<script setup>))
        • [1. 基础使用](#1. 基础使用)
        • [2. 多 Store / 异步示例](#2. 多 Store / 异步示例)
      • 五、高级特性
        • [1. 状态持久化(刷新不丢失)](#1. 状态持久化(刷新不丢失))
        • [2. reset / subscribe / onAction](#2. reset / subscribe / onAction)
      • [六、Pinia vs Vuex(核心区别)](#六、Pinia vs Vuex(核心区别))
      • 七、最佳实践

Pinia 是 Vue 官方推荐的新一代状态管理库 ,专为 Vue 3 设计(兼容 Vue 2),是 Vuex 的精神继任者。它以轻量、简洁、类型安全、模块化为核心优势,彻底简化 Vue 状态管理。

一、Pinia 核心介绍

1. 核心优势
  • API 极简 :去掉 Vuex 的 mutations,同步/异步逻辑统一在 actions 处理
  • 模块化扁平 :每个 store 天然独立、无嵌套、无命名空间冲突
  • TS 友好:原生类型推导,无需额外配置
  • 极致轻量:gzip 后约 1KB,几乎无性能负担
  • 组合式友好:完美适配 Vue 3 Composition API
  • DevTools 集成:支持时间旅行、热更新、状态追踪
  • SSR 支持:无缝兼容服务端渲染
2. 核心概念
  • Store :全局状态仓库,用 defineStore 创建
  • State :存储响应式数据(类似组件 data
  • Getters :基于 State 的计算属性(类似 computed
  • Actions :修改 State 的方法(支持同步/异步,替代 mutations+actions

二、Vue 3 中配置 Pinia

1. 安装
bash 复制代码
npm install pinia
# 或
yarn add pinia
pnpm add pinia
2. 全局注册(main.ts/main.js)
typescript 复制代码
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'

const app = createApp(App)
const pinia = createPinia() // 创建 Pinia 实例
app.use(pinia) // 注册到 Vue
app.mount('#app')

三、Store 定义(两种风格)

方式 1:选项式(Options API,兼容 Vue 2)
typescript 复制代码
// src/stores/counter.ts
import { defineStore } from 'pinia'

// 第一个参数:store 唯一 ID(必须全局唯一)
export const useCounterStore = defineStore('counter', {
  // 1. 状态(必须箭头函数返回对象)
  state: () => ({
    count: 0,
    name: 'Pinia Counter'
  }),

  // 2. 计算属性(带缓存)
  getters: {
    // 直接访问 state
    doubleCount: (state) => state.count * 2,
    // 访问其他 getter 用 this
    doubleCountPlusOne(): number {
      return this.doubleCount + 1
    }
  },

  // 3. 动作(同步/异步,修改 state)
  actions: {
    // 同步
    increment() {
      this.count++
    },
    // 异步(async/await)
    async incrementAsync(delay = 1000) {
      await new Promise(resolve => setTimeout(resolve, delay))
      this.count++
    },
    // 批量重置
    reset() {
      this.count = 0
      this.name = 'Reset'
    }
  }
})
方式 2:组合式(Composition API,Vue 3 推荐)
typescript 复制代码
// src/stores/user.ts
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'

export const useUserStore = defineStore('user', () => {
  // 1. 状态(ref/reactive 定义)
  const userInfo = ref({ name: '', age: 0 })
  const token = ref('')
  const isLoading = ref(false)

  // 2. 计算属性(computed 替代 getters)
  const isAdult = computed(() => userInfo.value.age >= 18)
  const userName = computed(() => userInfo.value.name || '未登录')

  // 3. 动作(普通函数,同步/异步)
  function setUser(info) {
    userInfo.value = info
  }

  async function login(account, pwd) {
    isLoading.value = true
    try {
      // 模拟接口请求
      const res = await fetch('/api/login', {
        method: 'POST',
        body: JSON.stringify({ account, pwd })
      })
      const data = await res.json()
      token.value = data.token
      userInfo.value = data.user
      return true
    } catch (err) {
      console.error('登录失败', err)
      return false
    } finally {
      isLoading.value = false
    }
  }

  // 必须返回暴露给组件
  return {
    userInfo,
    token,
    isLoading,
    isAdult,
    userName,
    setUser,
    login
  }
})

四、组件中使用(<script setup>)

1. 基础使用
vue 复制代码
<template>
  <div>
    <h2>{{ counter.name }}</h2>
    <p>计数:{{ counter.count }}</p>
    <p>双倍:{{ counter.doubleCount }}</p>
    <p>双倍+1:{{ counter.doubleCountPlusOne }}</p>
    <button @click="counter.increment">+1</button>
    <button @click="counter.incrementAsync(1500)">异步+1</button>
    <button @click="counter.reset">重置</button>

    <!-- 解构(必须用 storeToRefs 保持响应式) -->
    <p>解构计数:{{ count }}</p>
  </div>
</template>

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

// 1. 获取 store 实例
const counter = useCounterStore()

// 2. 响应式解构(关键!)
const { count, doubleCount } = storeToRefs(counter)

// 3. 直接修改(简单场景)
const setDirect = () => {
  counter.count = 100
}

// 4. $patch 批量修改(推荐)
const batchUpdate = () => {
  counter.$patch({
    count: 50,
    name: '批量更新'
  })
  // 函数形式(复杂逻辑)
  counter.$patch((state) => {
    state.count += 10
    state.name = '函数批量'
  })
}
</script>
2. 多 Store / 异步示例
vue 复制代码
<template>
  <div>
    <p>用户:{{ userStore.userName }}</p>
    <p>成年:{{ userStore.isAdult ? '是' : '否' }}</p>
    <button @click="handleLogin" :disabled="userStore.isLoading">
      {{ userStore.isLoading ? '登录中...' : '登录' }}
    </button>
  </div>
</template>

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

const handleLogin = async () => {
  const success = await userStore.login('admin', '123456')
  if (success) alert('登录成功!')
}
</script>

五、高级特性

1. 状态持久化(刷新不丢失)

安装插件:

bash 复制代码
npm install pinia-plugin-persistedstate

注册(main.ts):

typescript 复制代码
import { createPinia } from 'pinia'
import persist from 'pinia-plugin-persistedstate'

const pinia = createPinia()
pinia.use(persist) // 注册持久化

Store 开启:

typescript 复制代码
export const useUserStore = defineStore('user', {
  state: () => ({ token: '' }),
  persist: true, // 全量持久化(localStorage)
  // 或自定义
  persist: {
    key: 'app-user', // 存储 key
    paths: ['token'], // 仅持久化 token
    storage: sessionStorage // 切换存储
  }
})
2. reset / subscribe / $onAction
typescript 复制代码
// 重置 state(选项式)
counter.$reset()

// 监听 state 变化
counter.$subscribe((mutation, state) => {
  console.log('状态变更', mutation, state)
})

// 监听 actions
counter.$onAction(({ name, after, onError }) => {
  console.log('Action 开始:', name)
  after(() => console.log('Action 完成'))
  onError(err => console.error('Action 错误', err))
})

六、Pinia vs Vuex(核心区别)

特性 Pinia Vuex 3/4
核心概念 state、getters、actions state、getters、mutations、actions
异步处理 actions 直接支持 async/await actions 提交 mutations
模块化 天然扁平、独立 store 嵌套 modules、命名空间
TS 支持 原生、类型推导强 需额外配置、类型弱
体积 ~1KB 较大
组合式 完美适配 适配一般

七、最佳实践

  • 按业务拆分 Store:user、cart、setting、layout 等
  • 解构必用 storeToRefs:避免丢失响应式
  • 复杂修改用 $patch:批量更新、性能更优
  • 异步放 actions:统一逻辑、便于调试
  • 非共享状态用组件内 ref:不要滥用全局状态
相关推荐
李少兄2 小时前
网页应用化部署指南:基于 Edge 浏览器创建桌面快捷方式
前端·edge
IT_陈寒2 小时前
Python的异步陷阱:我竟然被await坑了一整天
前端·人工智能·后端
光影少年2 小时前
Android和iOS原生开发的基础知识对RN开发的重要性,RN打包发布时原生端需要做哪些配置?
android·前端·react native·react.js·ios
Fanfffff7202 小时前
从 6s 到 3s:一次电商前端性能优化实践的系统性总结
前端·性能优化
cypking2 小时前
npm 依赖包版本扫描提示插件Version Lens
前端·npm·node.js
还是大剑师兰特2 小时前
Vue3 Mixin 与 Vue2 Mixin 核心区别
前端·javascript·vue.js
188号安全攻城狮2 小时前
【前端基础知识】JavaScript 数组方法总结:从表格速查到分类详解
开发语言·前端·javascript·网络安全
qq_381338502 小时前
微前端架构深度实践:从 qiankun 到 Module Federation 的企业级方案
前端·架构
鱼干~2 小时前
【全栈知识点】全栈开发知识点
前端·人工智能·c#