vue3-pinia

好的!这份笔记专为你整理,涵盖了 Pinia 的核心知识点、实战写法和避坑指南。内容尽量精简结构化,方便你直接复制保存,随时查阅。


📦 Pinia 核心知识笔记(Vue 3 专用)

一句话概括 :Pinia 是 Vue 的官方状态管理库,用于在不同组件之间共享响应式数据(相当于前端内存里的全局数据库)。


1. 核心概念(三大支柱)

概念 作用 类比 Java / 后端
State(状态) 存储共享的数据 类的成员变量(属性)
Getters(计算属性) 基于 State 派生出新数据(类似 Vue 的 computed 类的 getter 方法(如 getFullName
Actions(动作) 修改 State 的方法(支持异步) 类的 setter 或 service 方法

2. 如何定义一个 Store(两种写法)

✅ 写法一:选项式(Options Store)------ 适合传统习惯

复制代码
import { defineStore } from 'pinia';

export const useCounterStore = defineStore('counter', {
  state: () => ({
    count: 0,
    name: 'Vue'
  }),
  getters: {
    doubleCount: (state) => state.count * 2,
  },
  actions: {
    increment() {
      this.count++; // 注意:在 actions 里用 this 访问 state
    },
    async fetchCount() {
      // 支持异步
      const res = await api.getCount();
      this.count = res.data;
    }
  }
});

✅ 写法二:组合式 API(Setup Store)------ 推荐写法(你目前学的)

复制代码
import { defineStore } from 'pinia';
import { ref, computed } from 'vue';

export const useUserStore = defineStore('user', () => {
  // 1. State(用 ref 定义响应式数据)
  const list = ref<User[]>([]);
  const loading = ref(false);

  // 2. Getters(用 computed 定义)
  const totalCount = computed(() => list.value.length);

  // 3. Actions(用普通函数定义)
  const setList = (newList: User[]) => {
    list.value = newList;
  };

  // 4. 将需要暴露的内容返回出去
  return { list, loading, totalCount, setList };
});

区别 :选项式用 this,组合式用 ref/computed 并直接 return。组合式更灵活,且 TypeScript 类型推导更好。


3. 在组件中使用 Store(⚠️ 重点:响应性丢失问题)

❌ 错误写法(解构会丢失响应性)

复制代码
const { list, setList } = useUserStore();
// list 变成了普通值,修改后页面不会更新!

✅ 正确写法 1:直接使用 store 对象

复制代码
const store = useUserStore();
// 模板中直接用 store.list,方法用 store.setList

✅ 正确写法 2:使用 storeToRefs 解构(保持响应性)

复制代码
import { storeToRefs } from 'pinia';

const store = useUserStore();
// 只能解构 state 和 getters(用 storeToRefs)
const { list, totalCount } = storeToRefs(store);
// actions 可以直接解构(不需要包起来)
const { setList } = store;

// 此时 list 和 totalCount 依然是响应式的!

4. 修改 State 的四种方式(由简到繁)

方式 代码示例 适用场景
1. 直接修改 store.list = [...] 简单赋值
2. 通过 Actions store.setList([...]) 推荐! 逻辑复用,便于调试
3. $patch 批量修改 store.$patch({ count: 1, name: 'hi' }) 同时改多个字段
4. $patch 函数式修改 store.$patch((state) => { state.count++ }) 复杂逻辑批量改

最佳实践 :所有修改尽量封装在 actions 里,避免业务逻辑散落在各个组件中。


5. Getters(派生状态)详解

复制代码
// 在 store 里定义
const filteredList = computed(() => {
  return list.value.filter(item => item.name.includes('张'));
});

// 在组件里使用(配合 storeToRefs 解构或直接 store.filteredList)
const { filteredList } = storeToRefs(store);

特点:Getter 会根据依赖自动缓存,只有依赖变化时才重新计算。


6. Actions(处理异步请求)------ 配合你的 Axios

复制代码
// store 里定义
const fetchUsers = async () => {
  loading.value = true;
  try {
    const res = await getUserList(); // 你封装的 Axios 方法
    list.value = res;
  } catch (error) {
    console.error('加载失败', error);
  } finally {
    loading.value = false;
  }
};

// 在组件里调用
await store.fetchUsers();

7. 跨 Store 通信(一个 Store 引用另一个)

复制代码
import { useUserStore } from './user';

export const useOrderStore = defineStore('order', () => {
  const userStore = useUserStore(); // 直接引入其他 Store

  const currentUser = computed(() => {
    // 拿到用户列表里的第一个
    return userStore.list[0];
  });

  return { currentUser };
});

8. 数据持久化(刷新页面数据丢失怎么办?)

Pinia 默认存在内存中,页面刷新就没了。通常配合插件 pinia-plugin-persistedstate

复制代码
npm i pinia-plugin-persistedstate

// main.ts 中配置
import { createPinia } from 'pinia';
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate';

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

// 在 store 中开启持久化
export const useUserStore = defineStore('user', () => {
  // ...
}, {
  persist: true // 自动存 localStorage
});

9. 在 Vue Router(路由守卫)中使用 Pinia

注意:在路由守卫中不能直接用 useUserStore()(因为 Pinia 还没激活)。要在 router 文件里这样写:

复制代码
// router/index.ts
router.beforeEach((to) => {
  // 确保 Pinia 已激活(Vue 应用已挂载)
  const userStore = useUserStore(); 
  if (to.meta.requiresAuth && !userStore.isLoggedIn) {
    return '/login';
  }
});

10. Vue Devtools 调试

Pinia 默认集成 Vue Devtools,在浏览器插件中可以:

  • 查看所有 Store 的当前 State。
  • 回放 Actions 的历史记录(时间旅行调试)。

🚀 速查速记口诀

  1. 定义仓库defineStore('id', () => { ... })
  2. 定义数据ref() / reactive() 包起来
  3. 定义计算computed() 返回派生值
  4. 定义方法 :普通函数,操作 value
  5. 暴露出去return { data, method }
  6. 组件使用const store = useXxxStore()
  7. 解构数据 :必须用 storeToRefs(store),方法不用
  8. 改数据:优先用 Actions,别到处直接改

这份笔记覆盖了 Pinia 95% 的日常开发场景。刚开始学可以先照着"组合式 API"的模板写,遇到复杂需求再回来看高级用法。祝学习顺利!😊

相关推荐
白泽_hunter1 小时前
搞懂 JS 数据类型:从 typeof 到手写完整类型判断,一张图理清
前端
日光倾2 小时前
TypeScript 随手记 —— 1
前端·javascript·typescript
自学it的攻城狮2 小时前
elpis-core ,koa实现的系统底座, 沉淀80% 的通用能力,剩下20% 用于定制化开发
前端
CappuccinoRose3 小时前
模块化体系
前端·import·export·es modules
AIDANHANG3 小时前
放开靠时间戳对日志前先核请求ID跨服务传播与采样关联
前端·人工智能
半生过往5 小时前
前端学 Java 课程笔记
java·前端·笔记
广州华水科技5 小时前
2026年单北斗GNSS变形监测系统推荐,破解水库安全监测难题
前端
独爱香菜6 小时前
Next.js 15 + Cloudflare Workers 实战:零中间件多语言 SEO 站点架构
前端
计算机魔术师6 小时前
DeepSeek、Qwen3比肩GPT-5,本地跑大模型的时代来了
前端