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"的模板写,遇到复杂需求再回来看高级用法。祝学习顺利!😊

相关推荐
CharlesYu019 小时前
前端性能优化的第一性原理,是不断缩短“用户发起意图 → 获得可用结果”之间的时间
前端
Bs_MoneyMagnet9 小时前
基于springboot+vue的医疗健康便民服务平台的设计与实现 源码+文档
java·vue.js·spring boot·后端·spring
平头哥技术团队9 小时前
Day 21 _ 页内锚点_给每段起个 id,目录写 href=_#id_,点一下页面就滚到那一段
前端·html·html5
子兮曰10 小时前
Bun v1.4.1 深度解析:从 Zig 到 Rust,一场 11 天、64 个 AI 代理的语言迁徙
前端·后端·bun
人民广场吃泡面10 小时前
什么是AI Agent?它又能给前端带来哪些效率提升?
前端·人工智能
中科三方11 小时前
两家域名注册商资质被ICANN终止:企业域名资产安全再受关注
前端·网络·安全·域名
bug总结11 小时前
uniapp vue3全局方法注册使用
前端·javascript·uni-app
华无丽言11 小时前
如何在宜搭中实现获取子表中的字段值赋值到父表中?
前端·javascript·低代码
IT_陈寒12 小时前
Vue的computed属性竟然坑了我一把
前端·人工智能·后端
威斯软科的老司机12 小时前
通俗讲解 CNN 图像识别、向量 Embedding、Softmax 概率计算这三块的简化原理
前端·人工智能·ui·数字孪生