引言
在开发Vue.js项目时,对于小型项目,我们通常可以通过组件之间的简单通信来管理状态。然而,当项目规模变大时,管理和维护这些状态就变得复杂和困难。为了解决这一问题,Vuex提供了一种集中式的状态管理方案。本文将通过一个示例,详细介绍如何在Vue.js项目中使用Vuex来管理应用状态。
Vuex是什么?
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 + 库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
为什么要选择Vuex?
Vuex的优势
-
集中管理数据流:Vuex将应用的状态集中存储在一个对象中,所有组件都可以访问和修改这个状态。
-
明确的状态修改流程:通过Vuex,所有的状态修改都必须遵循特定的流程,确保状态的可预测性和可维护性。
-
方便的调试工具:Vuex提供了强大的调试工具,可以帮助开发者追踪和调试状态的变化。
这里我们提出两个问题
1.多个视图依赖于同一状态,传参的方法对于多层嵌套的组件将会非常繁琐,并且对于兄弟组件间的状态传递无能为力。
2.来自不同视图的行为需要变更同一状态,我们经常会采用父子组件直接引用或者通过事件来变更和同步状态的多份拷贝。以上的这些模式非常脆弱,通常会导致无法维护的代码。
因此,我们为什么不把组件的共享状态抽取出来,以一个全局单例模式管理呢?在这种模式下,我们的组件树构成了一个巨大的“视图”,不管在树的哪个位置,任何组件都能获取状态或者触发行为!
使用Vuex
首先,我们需要安装Vuex:
npm install vuex
使用Vuex插件
在main.js
文件中,我们将Vuex store注册为全局组件:
import { createApp } from 'vue'
import './style.css'
import App from './App.vue'
import store from './store' // 状态仓库
const app = createApp(App)
app
.use(store)
.mount('#app')
创建Vuex Store
在src目录下创建一个store文件夹,并在下面创建一个index.js,定义全局状态
import {createStore} from 'vuex' // 只有一个store
// 全局状态
// 不再需要父兄子 陌生人之间数据传递
// 状态对象
const state = {
count : 0 , // 计数状态
user: null
}
const store = createStore({
state
})
export default store
我们定义了一个有count
的全局状态。
在组件中读取Vuex 状态
以下是App.vue
的内容
<script setup>
import { useStore } from 'vuex'
import { computed } from 'vue'
import AppHeader from './/components/AppHeader.vue'
const store = useStore() // hooks 编程
console.log(store.state.count);
const count = computed(() => store.state.count)
</script>
<template>
{{ count }}
<app-header />
</template>
<style scoped></style>
在这个组件中,我们通过useStore
钩子获取Vuex store实例,并通过computed
函数来计算count
状态。这样,我们可以在模板中显示count
的值。同时我们还引入了一个子组件。
在子组件中读取Vuex状态
接下来,我们在子组件中读取Vuex状态。以下是AppHeader.vue
文件的内容:
<template>
<div class="app-header">
<nav-list />
</div>
</template>
<script setup>
import NavList from './NavList.vue';
</script>
<style lang="scss" scoped>
.app-header {
/* 样式定义 */
}
</style>
在这个示例中,AppHeader.vue
组件包含了一个NavList.vue
组件。接下来是NavList.vue
文件的内容:
<template>
<div class="nav-list">
{{ count }}
</div>
</template>
<script setup>
import { useStore } from 'vuex';
import { computed } from 'vue';
const store = useStore();
const count = computed(() => store.state.count); // 读取count状态
</script>
<style lang="scss" scoped>
.nav-list {
/* 样式定义 */
}
</style>
在NavList.vue
组件中,我们同样使用了useStore
钩子和computed
函数来读取count
状态。
这样,无论是在父组件还是子组件中,我们都能方便地访问和使用Vuex状态。
在组件中修改Vuex状态
接下来,让我们看看如何在组件中修改Vuex状态。以下是修改后的index.js
文件内容:
import {createStore} from 'vuex' // 只有一个store
// 全局状态
// 不再需要父兄子 陌生人之间数据传递 login
// 状态对象
const state = {
count : 0 , // 计数状态
user: null
}
// 修改,要按流程 动作
const actions ={
increment: ({commit}) => {
console.log('////');
// commit 会提交一项修改 提交给mutations
commit('increment') }
}
// 所有状态的修改都要经过mutations
// 只有mutations 可以修改状态
const mutations ={
increment(state){
console.log("??????");
state.count++
}
}
// 除了读操作, 对写操作非常严格
const store = createStore({
state,
mutations,
actions
})
export default store
我们定义了一个名为mutations
的对象,其中有一个名为increment
的mutation包含可以修改状态的方法。increment
方法接收当前的状态state
作为参数,并直接修改count
属性的值。在这里,每次调用increment
mutation时,count
的值都会增加1。
然后,我们定义了一个名为actions
的对象,其中包含可以调度(dispatch)mutations的方法。每次调用increment
action时,它会提交increment
mutation,从而修改状态。
最后,修改store,新添加mutations
和actions
。
以下是修改后的 App.vue
<script setup>
import { useStore } from 'vuex'
import { computed } from 'vue'
import AppHeader from './/components/AppHeader.vue'
const store = useStore() // hooks 编程
console.log(store.state.count);
const count = computed(() => store.state.count)
const increment = () =>{
// 派遣 increment action
store.dispatch('increment')
}
</script>
<template>
{{ count }}
<button @click="increment">+</button>
<app-header />
</template>
<style scoped></style>
新添加一个按钮,并绑定一个一个事件increment
。我们通过点击按钮触发increment
方法,该方法会派遣一个increment
action,从而修改count
状态。
这样,祖孙组件之间数据修改也能同步!
需要注意的是控制台先打印 ////
再打印 ??????
,可以看出来,是先执行actions,actions提交了一份修改给mutations,然后再修改状态。
总结
通过本文的示例,展示了如何在Vue.js项目中使用Vuex来管理应用状态。介绍了Vuex的基本概念,包括state、actions和mutations,以及如何在组件中读取和修改状态。通过集中管理状态和明确的状态修改流程,Vuex能够帮助我们更好地维护和调试大型Vue.js应用。如果觉得文章对你有帮助,可以点个赞哦。