Vuex和Pinia都是Vue.js应用程序中的状态管理库,虽然两种状态管理库的vue2,vue3都兼容,但是更推荐vue2(vuex),vue3(pinia)
Vuex
Vuex是Vue.js官方提供的状态管理库,它借鉴了Flux和Redux的设计思想,将应用的状态(state)集中管理于单个全局状态树中。
核心概念
State:存储应用程序的状态
Getters:允许在Vuex store中定义计算属性,从state中派生出一些状态。
Mutations:唯一允许修改状态的地方,每个mutation都有一个字符串类型的事件类型(type)和一个回调函数(handler),它们接受state作为第一个参数。
Actions:类似于mutations,但不同之处在于它们提交的是mutations,而不是直接变更状态。Actions可以包含任意异步操作,是处理异步逻辑的好地方。
工作原理
Vuex通过一种响应式的方式来管理状态的变化,配合Vue.js的单向数据流,使得状态的变化可以被追踪和调试。
特性
集中管理状态,使得状态管理更加清晰和可维护。
支持模块化,可以将store分割成多个模块,每个模块拥有自己的state、getters、mutations、actions,提高代码的可读性和可维护性。
提供了严格模式,可以帮助检测state的变更是否来源于mutation。
适用场景
适用于大型、复杂的Vue.js应用程序,特别是需要集中管理大量状态、处理复杂状态逻辑或需要插件集成的场景。
Vue2中使用Vuex
- 安装Vuex
npm install vuex --save
yarn add vuex
2.创建vuex仓库,在src目录下新建store文件夹,并新建一个js文件
// store/index.js
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
export default new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++;
},
decrement (state) {
state.count--;
}
},
actions: {
incrementAsync ({ commit }) {
setTimeout(() => {
commit('increment');
}, 1000);
}
},
getters: {
doubleCount: state => state.count * 2
}
});
3.在main.js将store注册到全局组件中
import Vue from 'vue'
import App from './App.vue'
import store from './store'
Vue.config.productionTip = false
new Vue({ //实例
store, //仓库挂载
render: h => h(App),
}).$mount('#app')
4.在子组件中使用store里调用store的数据和方法,用helper函数进行映射能更加简洁的使用store的属性方法,为什么this.$store会指向仓库,因为在vue2中this指向当前实例,但是我们在main.js中只new了一个vue实例App,然后我们又把仓库挂载到了实例上,以后导入更多的东西比如vue-router之类的也可以通过this.$router指向挂载在实例上的router.
<!-- Counter.vue -->
<template>
<div>
<p>Count: {{ count }}</p> //不映射情况下 = this.$store.state.count
<p>Double Count: {{ doubleCount }}</p> //不映射情况下 = this.$store.getters.count
<button @click="increment">Increment</button>
<button @click="decrement">Decrement</button>
<button @click="incrementAsync">Increment Async</button>
</div>
</template>
<script>
import { mapState, mapMutations, mapActions, mapGetters } from 'vuex';
export default {
computed: {
...mapState(['count']),
...mapGetters(['doubleCount'])
},
methods: {
...mapMutations(['increment', 'decrement']),
...mapActions(['incrementAsync'])
}
};
</script>
//使用vuex中的函数mapState, mapMutations, mapActions, mapGetters进行映射,映射后可以直接调用store里的属性方法
//那如果不使用help函数映射,将会长这个样子
<!-- <script>
export default {
computed: {
// 直接访问 state
count() {
return this.$store.state.count;
},
// 直接访问 getters
doubleCount() {
return this.$store.getters.doubleCount;
}
},
methods: {
// 直接调用 mutations
increment() {
this.$store.commit('increment');
},
decrement() {
this.$store.commit('decrement');
},
// 直接调用 actions
incrementAsync() {
this.$store.dispatch('incrementAsync');
}
}
};
</script> -->
5.在父组件中导入子组件
<template>
<div>
<test />
</div>
</template>
<script>
import test from './test/test';
export default {
name: 'App',
components: {
test
}
}
</script>
<style></style>
测试页面
总结:Vuex的四大核心概念state-存数据,getters-存要通过计算的数据,mutation存同步变更数据的方法,actions存异步调用mutation方法变更数据的方法,仓库创建完后挂载到全局组件中,在组件中使用store时,需要export default,state和getters数据要写在computed计算属性里面,mutations和actions要写在methods里面。当然核心概念里面还有一个module(并不是用很多就不讲太深了),然后我们要创建使用多个仓库时,要把仓库模块化比如这种情况我们需要在store里面创建一个module文件夹,然后把要创建的仓库全部放进去,不用再import什么vuex,直接export就行,然后要在模块化组件开启命名空间,再统一导入到index.js里面的modules里面
Pinia
Pinia是Vue作者维护的另一个状态管理库,其目的是设计一个拥有组合式 API 的 Vue 状态管理库。所以可以说它是几乎完全服务于vue3的。
核心概念
State:存储应用程序的状态
Getters:是 store 的计算属性 (computed)
Actions:类似于vuex中actions和mutations的继承,可以包含任意同步和异步操作。
工作原理
Pinia的工作原理是基于Vue.js的响应式数据模型。它提供了一个全局的存储库(store)来管理应用程序中的状态。每个store都是独立的,并且拥有自己的状态(state)、getter和action。Pinia通过Vue的响应式系统来确保当store中的状态发生变化时,相关的组件能够自动更新。
具体来说,Pinia使用createPinia
函数来创建一个Pinia实例,这个实例可以看作是一个全局的store容器。通过调用defineStore
函数,开发者可以创建新的store,这些store被自动添加到Pinia实例中。在组件中,开发者可以使用useStore
函数(或自定义的store钩子)来获取对应的store实例,并访问其中的状态和方法。
特性
Pinia具有以下几个显著特性:
直观性:Pinia允许开发者像定义Vue组件一样定义store,这使得状态管理变得更加直观和易于理解。
完整的TypeScript支持:Pinia提供了完整的TypeScript支持,使得开发者可以在编写状态管理逻辑时获得更好的类型检查和代码提示。
去除mutations:与Vuex不同,Pinia去除了mutations的概念,只保留了state、getters和actions。这使得状态更新更加直接和简单。
actions支持同步和异步操作:Pinia的actions方法既可以处理同步逻辑,也可以处理异步逻辑,如发送网络请求等。
Vue Devtools支持:Pinia支持Vue Devtools,这是一个浏览器扩展,允许开发者在浏览器中直接查看和调试Vue应用程序的状态。
模块化:Pinia支持将状态划分为不同的模块(store),每个模块对应一个特定的功能或数据领域。这使得状态管理更加清晰和有序。
轻量级:Pinia的体积非常小(只有约1kb),对应用程序的性能影响微乎其微。
适用场景
Pinia主要适用于以下场景:
Vue.js应用程序中的状态管理:Pinia是专门为Vue.js设计的状态管理库,它提供了简单而强大的API来管理应用程序中的状态。
跨组件状态共享:在Vue应用程序中,经常需要在多个组件之间共享状态。Pinia提供了一个集中的位置来存储和管理这些状态,使得跨组件的状态共享变得简单直接。
复杂逻辑处理:对于需要处理复杂逻辑(如用户登录、数据加载等)的应用程序,Pinia的actions方法提供了强大的支持。
模块化开发:对于大型应用程序,Pinia支持将状态划分为不同的模块,这使得代码更加清晰、易于维护和复用。
vue3中使用Pinia
1.安装pinia
yarn add pinia # 或者使用 npm npm install pinia
2.将pinia配置到全局组件中
// main.js
import { createApp } from 'vue';
import App from './App.vue';
import { createPinia } from 'pinia';
const pinia = createPinia()
const app = createApp(App);
app.use(pinia);
app.mount('#app');
3.在 src/stores
目录下创建一个新的文件,比如 data.js
,来定义你的状态(我比较喜欢叫状态为属性方法数据之类的)。pinia中的actions类似于vuex中的mutations和actions的集成,所以既可以声明同步函数,也可以写异步函数。
// src/store/data.js
import { defineStore } from 'pinia';
export const useDataStore = defineStore('data', {
state: () => ({
count: 0,
}),
actions: {
increment () {
this.count++;
},
decrement () {
this.count--;
},
reset () {
this.count = 0;
},
},
});
4.在组件中使用
<!-- test.vue -->
<template>
<div>
<!-- 使用计算属性来显示 count 的值 -->
<p>Count: {{ countDisplay }}</p>
<button @click="increment">Increment</button>
<button @click="decrement">Decrement</button>
<button @click="reset">Reset</button>
</div>
</template>
<script>
import { computed } from 'vue';
import { useDataStore } from '../store/data';
export default {
setup () {
const dataStore = useDataStore();
// 使用 computed 创建一个计算属性来监测 count
const countDisplay = computed(() => {
return dataStore.count;
});
// 也可以直接从 store 中解构 actions,因为它们是函数,不需要响应性
const { increment, decrement, reset } = dataStore;
return {
countDisplay, // 返回计算属性
increment, // 返回 increment action
decrement, // 返回 decrement action
reset, // 返回 reset action
};
},
};
</script>
5.在父组件中引用
<template>
<div id="app">
<Test />
</div>
</template>
<script setup>
import Test from './components/Test.vue';
</script>
测试页面
刚刚子组件使用pinia store 的时候忘了使用computed监听数据,导致count无法响应实时更新。
好了今天的分享就到这里反正pinia+vue3很好用谁用谁知道,vue2带着你的vuex滚出去(个人使用体验私密马赛)。