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

相关推荐
半点寒12W1 小时前
微信小程序实现路由拦截的方法
前端
某公司摸鱼前端2 小时前
uniapp socket 封装 (可拿去直接用)
前端·javascript·websocket·uni-app
要加油哦~2 小时前
vue | 插件 | 移动文件的插件 —— move-file-cli 插件 的安装与使用
前端·javascript·vue.js
小林学习编程2 小时前
Springboot + vue + uni-app小程序web端全套家具商场
前端·vue.js·spring boot
柳鲲鹏2 小时前
WINDOWS最快布署WEB服务器:apache2
服务器·前端·windows
weixin-a153003083163 小时前
【playwright篇】教程(十七)[html元素知识]
java·前端·html
ai小鬼头4 小时前
AIStarter最新版怎么卸载AI项目?一键删除操作指南(附路径设置技巧)
前端·后端·github
wen's4 小时前
React Native 0.79.4 中 [RCTView setColor:] 崩溃问题完整解决方案
javascript·react native·react.js
一只叫煤球的猫4 小时前
普通程序员,从开发到管理岗,为什么我越升职越痛苦?
前端·后端·全栈
vvilkim4 小时前
Electron 自动更新机制详解:实现无缝应用升级
前端·javascript·electron