浅谈vuex和pinia的区别
文章目录
- 介绍
- 核心概念
- 用法区别
- 导入
- state
- getters
- Mutations
- Actions
- 工作原理
- 优缺点
本篇文章主要展示vuex和pinia的区别,详情使用请看博主其他文章或者官方文档
vuex官网:https://vuex.vuejs.org/zh/guide/
pinia官网:https://pinia.vuejs.org/zh/introduction.html
介绍
VueX:VueX 是 Vue.js 官方提供的状态管理库。它基于 Flux 架构模式,提供了一个中央状态存储器来管理应用程序中的状态。VueX 可以通过 mutations、actions 和 getters 等概念来修改和处理状态的变更,同时具有强大的工具和插件支持。
Pinia 是 Vue 的专属状态管理库,它允许你跨组件或页面共享状态。如果你熟悉组合式 API 的话,你可能会认为可以通过一行简单的 export const state = reactive({}) 来共享一个全局状态。对于单页应用来说确实可以,但如果应用在服务器端渲染,这可能会使你的应用暴露出一些安全漏洞。 而如果使用 Pinia,即使在小型单页应用中,你也可以获得如下功能:
- Devtools 支持
- 追踪 actions、mutations 的时间线
- 在组件中展示它们所用到的 Store
- 让调试更容易的 Time travel
- 热更新
- 不必重载页面即可修改 Store
- 开发时可保持当前的 State
- 插件:可通过插件扩展 Pinia 功能
- 为 JS 开发者提供适当的 TypeScript 支持以及自动补全功能。
- 支持服务端渲染
核心概念
vuex
:State,Getter,Mutation,Action,Module
pinia
:State,Getter,Action,store
显而易见,pinia去除了Mutation
用法区别
导入
vuex
//store.js
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
pinia
//main.js
import { createPinia } from 'pinia';
import { createApp } from 'vue';
import App from './App.vue';
const app = createApp(App);
const pinia = createPinia();
app.use(pinia);
app.mount('#app');
// store.js
import { defineStore } from 'pinia';
state
vuex
const store = new Vuex.Store({
state: {
count: 0
}})
组件中使用
直接使用:
<template>
<p>{{ $store.state.count }}</p>
</template>
通过映射
import { mapState} from 'vuex';
export default {
computed: {
...mapState(['count'])
}}
pinia
export const useCounterStore = defineStore('counter', {
state: () => ({
count: 0,
name: 'Pinia'
}),})
组件中简单使用
<template>
<div>
<p>Count: {{ counterStore.count }}</p>
<p>name: {{ counterStore.name }}</p>
</div>
</template>
<script setup>
import { useCounterStore } from '@/stores/counter';
const counterStore = useCounterStore();
</script>
getters
vuex
const store = new Vuex.Store({
getters: {
doubleCount: state => state.count * 2
}
});
组件中使用
简单使用
$store.getters.doubleCount
使用映射
import { mapGetters} from 'vuex';
computed: {
...mapGetters(['doubleCount'])
},
pinia
store.js
export const useCounterStore = defineStore('counter', {
getters: {
doubleCount: (state) => state.count * 2
},})
在组件中使用
<template>
<div>
<p>Double Count: {{ counterStore.doubleCount }}</p>
</div>
</template>
<script setup>
import { useCounterStore } from '@/stores/counter';
const counterStore = useCounterStore();
</script>
Mutations
mutations 是唯一能够直接修改 state 的方法,Vuex 强制要求使用同步函数来更改状态。每个 mutation 都有一个字符串类型的事件类型(type)和一个回调函数(handler),回调函数的第一个参数是 state。
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment(state) {
state.count++;
}
}
});
调用
store.commit('increment');
pinia没有mutations属性
Actions
vuex
actions 用于提交 mutations,但不同的是,actions 支持异步操作。在 actions 中执行异步操作(如 API 请求)后,再通过 commit 来触发 mutation 以修改状态。
const store = new Vuex.Store({
mutations: {
increment(state) {
state.count++;
}
},
actions: {
incrementAsync({ commit }) {
setTimeout(() => {
commit('increment');
}, 1000);
}
}
})
在组件使用
<template>
<button @click="incrementAsync">Async Increment</button>
</template>
<script>
export default {
methods: {
incrementAsync() {
this.$store.dispatch('incrementAsync');
}
}
};
</script>
当然,如果actions多的话,你也可以选择使用映射
import { mapActions } from 'vuex';
methods: {
...mapMutations(['increment']),
...mapActions(['asyncIncrement'])
}
pinia
// store.js
import { defineStore } from 'pinia';
export const useStore = defineStore('main', {
state: () => ({
count: 0
}),
getters: {
doubleCount: (state) => state.count * 2
},
actions: {
increment() {
this.count++;
},})
在组件中使用
<template>
<div>
<button @click="counterStore.increment">Increment</button>
</div>
</template>
<script setup>
import { useCounterStore } from '@/stores/counter';
const counterStore = useCounterStore();
</script>
工作原理
vuex:
Vuex 基于以下机制来实现其核心功能:
响应式的 state:Vuex 利用 Vue.js 自身的响应式系统来确保 state 的变化会自动引发界面的更新。
单一状态树:Vuex 通过单一的状态树将所有的状态集中管理,每个组件都可以通过这个状态树访问和修改数据,避免了多层嵌套传递数据的问题。
不可变的 state:只有通过提交 mutation 才能修改 state,这种方式确保了状态的可追踪性。通过 Vue 开发工具,开发者可以轻松地查看每一次 mutation 是如何改变状态的。
pinia
-
创建 Pinia 实例:
createPinia()
用于生成 Pinia 实例,这个实例你可以将其看作为一个全局的 store 容器,用来保存所有的 Vuex store。 -
创建 Store:
使用createStore
可以创建一个新的 store,这个 store 可看做是一个独立的状态管理空间,其中包含了 state、getters 和 actions,被创建的 store 实例会被自动添加到 Pinia 实例中。 -
使用 Store:
我们通过在组件中调用用createStore
创建的 store 函数,来获取对应的 Pinia store 的实例。然后,我们就可以访问其中的 state、getters,或者执行 actions 里定义的方法。 -
监听 Store 变化:
我们可以使用 Vue 的watch
和watchEffect
函数来监听 store 中 state 或 getters 的变化,以便在这些内容改变时执行相应的操作。 -
整合到 Vue App 中:
创建的 Pinia 实例需要使用app.use()
安装到 Vue App 中,以便 Pinia 与 Vue App 一同工作,提供全局的状态管理能力。
优缺点
Vuex 的优点
- 成熟稳定:Vuex 已经存在很长时间,社区和文档非常完善。
- 模块化支持:Vuex 提供了强大的模块化支持,可以将状态拆分成多个模块进行管理。
- 严格的约束:Vuex 的严格约束有助于保持代码的一致性和可维护性。
Vuex 的缺点
-
语法复杂:Vuex 的语法相对较为复杂,初学者可能需要一些时间来适应。
-
冗长的代码:由于 Vuex 的严格约束,代码可能会变得冗长和重复。
Pinia 的优点
- 简洁的 API:相比 Vuex,Pinia 不再需要 mutations,状态的修改可以直接通过 actions 或者直接修改 state,减少了模板代码,使状态管理更直观。
- 支持组合式 API:Pinia 完美集成了 Vue 3 的组合式 API(Composition API),和 setup
直接结合使用,减少了复杂性。 - TypeScript 支持:Pinia 原生支持 TypeScript,提供类型推断和自动完成,让开发者在使用 Pinia
时更加方便,减少了手动添加类型的麻烦。 - 模块自动化:不需要像 Vuex 那样手动注册模块,Pinia 的 store 是独立的,自动按需加载,无需管理模块的注册和取消注册。
- 开发工具支持:Pinia 支持 Vue Devtools,并提供了时间旅行和状态快照功能,方便调试。
Pinia 的缺点
- 社区支持较少:虽然 Pinia 是官方推荐的 Vue 3 状态管理工具,但它相对于 Vuex
来说是较新的库,社区资源和插件的生态系统还没有 Vuex 丰富。 - 学习成本:对于已经熟悉 Vuex 的开发者,迁移到 Pinia
需要一些学习时间,尤其是在大型项目中迁移状态管理可能会涉及较大的代码修改。 - 不支持 Vue 2:Pinia 是专门为 Vue 3 设计的,无法与 Vue 2 一起使用。如果需要在 Vue 2中使用状态管理,仍然需要使用 Vuex。
- 性能:虽然 Pinia 的性能相较 Vuex 有所提升,但在非常大规模的项目中,状态管理的性能瓶颈问题可能仍然存在。此时需要配合 Vue
的响应式原理和一些手动优化来保证性能。