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

相关推荐
乔冠宇几秒前
CSS3中的新增属性总结
前端·javascript·css3
e***5823几秒前
Spring Cloud GateWay搭建
android·前端·后端
青衫码上行1 小时前
【Java Web学习 | 第15篇】jQuery(万字长文警告)
java·开发语言·前端·学习·jquery
x***13393 小时前
【MyBatisPlus】MyBatisPlus介绍与使用
android·前端·后端
z***75155 小时前
【Springboot3+vue3】从零到一搭建Springboot3+vue3前后端分离项目之后端环境搭建
android·前端·后端
fruge6 小时前
仿写优秀组件:还原 Element Plus 的 Dialog 弹窗核心逻辑
前端
an86950017 小时前
vue新建项目
前端·javascript·vue.js
w***95497 小时前
SQL美化器:sql-beautify安装与配置完全指南
android·前端·后端
顾安r8 小时前
11.22 脚本打包APP 排错指南
linux·服务器·开发语言·前端·flask
万邦科技Lafite8 小时前
1688图片搜索商品API接口(item_search_img)使用指南
java·前端·数据库·开放api·电商开放平台