【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 中没有模块化的概念了,就更不存在需要使用命名空间了。

相关推荐
程序员mine2 分钟前
Web服务密码存储安全详解:从哈希到密钥派生的演进
前端·后端
如果超人不会飞2 分钟前
TinyRobot Sender打造强大的AI聊天输入体验
前端·vue.js
爱吃生蚝的于勒7 分钟前
QT开发第三章——常用控件
linux·服务器·开发语言·前端·javascript·c++·qt
xuankuxiaoyao20 分钟前
Axios-图书列表案例
开发语言·前端·javascript
meilindehuzi_a22 分钟前
深入理解 JavaScript 数据类型:从冯·诺依曼架构到八种数据类型
javascript
影寂ldy23 分钟前
C# 多播委托
前端·javascript·c#
dy171724 分钟前
Vue3 多文件上传
前端·javascript·vue.js
带娃的IT创业者24 分钟前
深度解析 Bun:重新定义 JavaScript 运行时的性能边界
开发语言·javascript·node.js·ecmascript·bun·运行时
文阿花33 分钟前
Echarts实现3D饼状图
前端·javascript·echarts·饼状图
智码看视界40 分钟前
老梁聊全栈系列:Vue2与Vue3核心区别及学习路线指南
前端·vue.js·学习