Tailwind CSSTailwind CSS
Home
  • Tailwind CSS 书籍目录
  • Vue 3 开发实战指南
  • React 和 Next.js 学习
  • TypeScript
  • React开发框架书籍大纲
  • Shadcn学习大纲
  • Swift 编程语言:从入门到进阶
  • SwiftUI 学习指南
  • 函数式编程大纲
  • Swift 异步编程语言
  • Swift 协议化编程
  • SwiftUI MVVM 开发模式
  • SwiftUI 图表开发书籍
  • SwiftData
  • ArkTS编程语言:从入门到精通
  • 仓颉编程语言:从入门到精通
  • 鸿蒙手机客户端开发实战
  • WPF书籍
  • C#开发书籍
learn
  • Java编程语言
  • Kotlin 编程入门与实战
  • /python/outline.html
  • AI Agent
  • MCP (Model Context Protocol) 应用指南
  • 深度学习
  • 深度学习
  • 强化学习: 理论与实践
  • 扩散模型书籍
  • Agentic AI for Everyone
langchain
Home
  • Tailwind CSS 书籍目录
  • Vue 3 开发实战指南
  • React 和 Next.js 学习
  • TypeScript
  • React开发框架书籍大纲
  • Shadcn学习大纲
  • Swift 编程语言:从入门到进阶
  • SwiftUI 学习指南
  • 函数式编程大纲
  • Swift 异步编程语言
  • Swift 协议化编程
  • SwiftUI MVVM 开发模式
  • SwiftUI 图表开发书籍
  • SwiftData
  • ArkTS编程语言:从入门到精通
  • 仓颉编程语言:从入门到精通
  • 鸿蒙手机客户端开发实战
  • WPF书籍
  • C#开发书籍
learn
  • Java编程语言
  • Kotlin 编程入门与实战
  • /python/outline.html
  • AI Agent
  • MCP (Model Context Protocol) 应用指南
  • 深度学习
  • 深度学习
  • 强化学习: 理论与实践
  • 扩散模型书籍
  • Agentic AI for Everyone
langchain
  • Pinia 的安装与基本使用

Pinia 的安装与基本使用

Pinia 是 Vue 3 推荐的状态管理库,以其轻量、简洁和与 Composition API 的无缝集成受到开发者青睐。本节将详细讲解 Pinia 的安装步骤、基本使用方法,并通过示例展示如何在 Vue 3 项目中创建和管理 Store,帮助你快速上手这一现代状态管理工具。

安装 Pinia

Pinia 的安装过程简单,直接通过包管理器添加即可。

步骤

  1. 安装 Pinia: 在 Vue 3 项目中运行:
    npm install pinia
    

或使用 Yarn:

yarn add pinia
  1. 集成到项目: 修改 main.js 文件,将 Pinia 注册到应用中:
    // src/main.js
    import { createApp } from 'vue';
    import { createPinia } from 'pinia';
    import App from './App.vue';
    
    const app = createApp(App);
    const pinia = createPinia();
    app.use(pinia);
    app.mount('#app');
    
  • 验证:安装完成后,Pinia 已全局可用,组件可以通过 useStore 访问 Store。

创建和管理 Store

Pinia 使用 defineStore 函数创建 Store,每个 Store 是一个独立的响应式状态容器。

基本用法

定义 Store

// src/stores/counter.js
import { defineStore } from 'pinia';
import { ref } from 'vue';

export const useCounterStore = defineStore('counter', () => {
  // 状态
  const count = ref(0);

  // 方法
  const increment = () => {
    count.value++;
  };

  const decrement = () => {
    count.value--;
  };

  return { count, increment, decrement };
});
  • 解析:
    • 'counter':Store 的唯一标识。
    • 返回对象:暴露状态和方法。

使用 Store

<!-- src/App.vue -->
<template>
  <div>
    <p>计数:{{ count }}</p>
    <button @click="increment">增加</button>
    <button @click="decrement">减少</button>
  </div>
</template>

<script>
import { useCounterStore } from '@/stores/counter';

export default {
  setup() {
    const store = useCounterStore();
    return {
      count: store.count,
      increment: store.increment,
      decrement: store.decrement
    };
  }
};
</script>
  • 效果:点击按钮,计数增加或减少,页面实时更新。
  • 特点:直接访问状态和方法,无需 Mutations。

添加 Getters

Pinia 使用 computed 定义 Getters,派生状态。

// src/stores/counter.js
import { defineStore } from 'pinia';
import { ref, computed } from 'vue';

export const useCounterStore = defineStore('counter', () => {
  const count = ref(0);
  
  const double = computed(() => count.value * 2);

  const increment = () => count.value++;
  const decrement = () => count.value--;

  return { count, double, increment, decrement };
});

使用

<template>
  <div>
    <p>计数:{{ count }}</p>
    <p>双倍:{{ double }}</p>
    <button @click="increment">增加</button>
  </div>
</template>

<script>
import { useCounterStore } from '@/stores/counter';

export default {
  setup() {
    const store = useCounterStore();
    return { count: store.count, double: store.double, increment: store.increment };
  }
};
</script>
  • 效果:显示计数及其双倍值,响应式更新。

异步操作

Pinia 的 Actions 是普通函数,支持异步逻辑。

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

export const useUserStore = defineStore('user', () => {
  const user = ref(null);

  const fetchUser = async (id) => {
    const response = await fetch(`https://jsonplaceholder.typicode.com/users/${id}`);
    user.value = await response.json();
  };

  return { user, fetchUser };
});

使用

<template>
  <div>
    <button @click="fetchUser(1)">获取用户</button>
    <p v-if="user">用户名:{{ user.name }}</p>
  </div>
</template>

<script>
import { useUserStore } from '@/stores/user';

export default {
  setup() {
    const store = useUserStore();
    return { user: store.user, fetchUser: store.fetchUser };
  }
};
</script>
  • 效果:点击按钮异步获取用户数据并显示。

基本操作

1. 修改状态

Pinia 允许直接修改状态:

store.count = 10; // 直接赋值
store.increment(); // 通过方法修改

2. 重置状态

使用 $reset 重置到初始状态:

// 添加 reset 方法
export const useCounterStore = defineStore('counter', () => {
  const count = ref(0);
  const increment = () => count.value++;
  return { count, increment };
});
<template>
  <button @click="$reset">重置</button>
</template>

<script>
import { useCounterStore } from '@/stores/counter';

export default {
  setup() {
    const store = useCounterStore();
    return store; // 直接返回整个 store
  }
};
</script>
  • 限制:$reset 只适用于 ref 和 reactive,复杂对象需手动实现。

3. 订阅状态变化

使用 $subscribe 监听状态变化:

store.$subscribe((mutation, state) => {
  console.log('状态变化:', state.count);
});

与 Composition API 集成

Pinia 天然支持 Composition API,可在 setup 中直接使用:

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

<script>
import { useCounterStore } from '@/stores/counter';

export default {
  setup() {
    const store = useCounterStore();
    return { store };
  }
};
</script>
  • 便捷性:无需额外封装,直接访问响应式状态。

项目结构建议

src/
├── stores/
│   ├── counter.js
│   ├── user.js
│   └── index.js  # 可选:统一导出
├── components/
└── main.js

统一导出(可选)

// src/stores/index.js
export * from './counter';
export * from './user';

注意事项

  1. 唯一 ID:
    • 每个 defineStore 的 ID 必须全局唯一。
  2. 状态管理范围:
    • 小型项目可直接用 ref 或 reactive,Pinia 更适合中大型应用。
  3. 调试:
    • 使用 Vue DevTools 查看和管理 Pinia Store。

综合示例

Store 定义

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

export const useTodoStore = defineStore('todo', () => {
  const todos = ref([]);
  
  const addTodo = (text) => {
    todos.value.push({ id: Date.now(), text, done: false });
  };

  const toggleTodo = (id) => {
    const todo = todos.value.find(t => t.id === id);
    if (todo) todo.done = !todo.done;
  };

  return { todos, addTodo, toggleTodo };
});

使用

<template>
  <div>
    <input v-model="newTodo" @keyup.enter="addTodo" placeholder="添加任务" />
    <ul>
      <li v-for="todo in todos" :key="todo.id" :class="{ done: todo.done }">
        <input type="checkbox" v-model="todo.done" @change="toggleTodo(todo.id)" />
        {{ todo.text }}
      </li>
    </ul>
  </div>
</template>

<script>
import { useTodoStore } from '@/stores/todo';

export default {
  setup() {
    const store = useTodoStore();
    const newTodo = ref('');
    
    const addTodo = () => {
      if (newTodo.value.trim()) {
        store.addTodo(newTodo.value);
        newTodo.value = '';
      }
    };

    return {
      todos: store.todos,
      toggleTodo: store.toggleTodo,
      newTodo,
      addTodo
    };
  }
};
</script>

<style scoped>
.done { text-decoration: line-through; }
</style>
  • 效果:添加任务并切换完成状态,列表实时更新。

总结

Pinia 的安装和使用非常直观,通过 defineStore 创建 Store,结合 ref 和 computed 管理状态和派生数据。其简洁的 API 和对 Composition API 的支持使其成为 Vue 3 的首选状态管理工具。掌握本节内容后,你可以轻松在项目中应用 Pinia。下一节将探讨模块化状态管理,进一步提升你的技能!

Last Updated:: 2/24/25, 10:55 AM