【Pinia】Pinia和Vuex对比

Pinia 是 Vue 官方团队成员专门开发的一个全新状态管理库,并且 Vue 的官方状态管理库已经更改为了 Pinia。 在 Vuex 官方仓库中也介绍说可以把 Pinia 当成是不同名称的 Vuex 5,这也意味不会再出 5 版本了。

优点

  1. 更加轻量级,压缩后提交只有1.6kb。

  2. 完整的 TS 的支持,Pinia 源码完全由 TS 编码完成。

Pinia 在与 TS 一起使用时,具有可靠的类型判断支持;Vuex 之前对 TS 的支持很不友好。

  1. 移除 mutations,只剩下 state 、 actions 、 getters,在store内部直接使用this使用state里的数据。

一旦 store 被实例化,就可以直接在 store 上访问 state、getters 和 actions 中定义的任何属性;而在使用 Vuex 的时候,更改状态需要纠结选取 mutation 还是 action。

  1. 不再有 Vuex 里多个 modules 的嵌套结构,可以定义多个 store 并灵活使用。

  2. 不会再有module的命名空间的概念,不需要记住他们的复杂关系。

  3. 支持服务端渲染(SSR)。

  4. 更友好的代码分割机制。

  5. 提供了 Pinia 状态持久化。配置 | Pinia Plugin Persistedstate

举例说明

针对第4点

Pinia版本:假设我们有一个购物车应用,需要管理用户信息和购物车商品信息,可以用两个 Store 来实现。

javascript 复制代码
// userStore.js
import { defineStore } from 'pinia';
export const useUserStore = defineStore('user', {
  state: () => ({
    name: '',
    age: 0,
  }),
  actions: {
    updateName(newName) {
      this.name = newName;
    },
  },
});

// cartStore.js
import { defineStore } from 'pinia';
export const useCartStore = defineStore('cart', {
  state: () => ({
    items: [],
  }),
  actions: {
    addItem(item) {
      this.items.push(item);
    },
  },
});

Vuex版本:在组件中,通过 this.$store 来访问状态,需要通过命名空间来区分模块,例如 this.$store.state.user.namethis.$store.commit('cart/addItem', item)

javascript 复制代码
// store.js
import { createStore } from 'vuex';
export default createStore({
  modules: {
    // 用户
    user: {
      state: {
        name: '',
        age: 0,
      },
      mutations: {
        updateName(state, newName) {
          state.name = newName;
        },
      },
    },
    // 购物车
    cart: {
      state: {
        items: [],
      },
      mutations: {
        addItem(state, item) {
          state.items.push(item);
        },
      },
    },
  },
});

针对第5点

Vuex 中,如果没有命名空间,多个模块有相同名称的方法,如模块A和模块B都有updateName,使用起来会冲突,因为 Vuex 不知道要调用哪个模块的 updateName

javascript 复制代码
// 模块 A
mutations: {
  updateName(state, newName) {
    state.name = newName;
  },
}

// 模块 B
mutations: {
  updateName(state, newName) {
    state.name = newName;
  },
}

通过命名空间namespaced: true,可以将每个模块的作用域限制在模块内部,避免冲突。

javascript 复制代码
// 模块 A
namespaced: true, 
mutations: {
  updateName(state, newName) {
    state.name = newName;
  },
}

// 模块 B
namespaced: true, 
mutations: {
  updateName(state, newName) {
    state.name = newName;
  },
}


// 组件中使用
this.$store.commit('moduleA/updateName', 'John');
this.$store.commit('moduleB/updateName', 'Jane');

当然,在 pinia 中没有模块化的概念了,就更不存在需要使用命名空间了。

相关推荐
张迅之27 分钟前
【React】Ant Design 5.x 实现tabs圆角及反圆角效果
前端·react.js·ant-design
@CLoudbays_Martin1129 分钟前
为什么动态视频业务内容不可以被CDN静态缓存?
java·运维·服务器·javascript·网络·python·php
蔗理苦2 小时前
2025-09-05 CSS3——盒子模型
前端·css·css3
二川bro2 小时前
第25节:VR基础与WebXR API入门
前端·3d·vr·threejs
上单带刀不带妹3 小时前
Node.js 的模块化规范是什么?CommonJS 和 ES6 模块有什么区别?
前端·node.js·es6·模块化
缘如风3 小时前
easyui 获取自定义的属性
前端·javascript·easyui
诗书画唱3 小时前
【前端教程】JavaScript 实现图片鼠标悬停切换效果与==和=的区别
开发语言·前端·javascript
光影少年3 小时前
前端上传切片优化以及实现
前端·javascript·掘金·金石计划
喜葵3 小时前
前端安全防护深度实践:从XSS到供应链攻击的全面防御
前端·安全·xss
_r0bin_3 小时前
分片上传-
前端·javascript·状态模式