Vue详细讲解Vuex状态管理的实现
什么是Vuex
Vuex是Vue.js的官方状态管理插件,它将组件之间共享的状态抽取出来,以一个全局单例模式管理,实现了在共享状态时一些问题的规避,使代码更容易理解和维护。
Vuex的状态管理机制
Vuex的状态管理机制可以从以下三个方面来解释:
State
状态是存储在Vuex store上的单一状态树,相当于Vue模板上的data。每一个Vuex应用的中央唯一数据存储中都有一个store实例,包含了所有的状态。可以通过store.state来访问。
// store.js
import Vuex from 'vuex'
import Vue from 'vue'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
count: 0
}
})
上面的代码实现了一个简单的store,包含了一个数值型state变量count,初始值为0。
可以在组件中通过this.$store.state.count来访问该状态。
Getter
Getter就是store的计算属性,相当于Vue模板上的computed。Vuex的store中,Getter相当于从store中派生方法的概念,在通过computed派生出新的属性时,Getter也可以根据需要派生出新的状态。
Getter接受state作为其第一个参数,可以定义计算属性,Getter会缓存计算结果并告诉你何时重新计算(当依赖的状态发生变化时)。
// store.js
export default new Vuex.Store({
state: {
todos: [
{ id: 1, text: 'todo1', done: true },
{ id: 2, text: 'todo2', done: false }
]
},
getters: {
doneTodos: state => {
return state.todos.filter(todo => todo.done)
}
}
})
在上面的代码中,我们新定义了一个Getter,返回已完成的列表。可以在组件中通过this.$store.getters.doneTodos来访问。这样,无论todos状态如何改变,只有当done属性变化时,该Getter才会被重新计算。
Mutation
Mutation是用于修改状态的唯一方法,相当于Vue模板上的methods。Mutation改变store中的状态的唯一方法是提交mutation,mutation就像事件一样来描述发生了什么,每个mutation都有一个字符串类型的操作命名,一个回调函数和一个payload,payload是通常会被作为回调函数的入参传进来。
Mutation必须是同步的,一旦提交了mutation,我们就可以确保state已经同步完成了更新。
// store.js
export default new Vuex.Store({
state: {
count: 0
},
mutations: {
increment: (state, payload) => {
state.count += payload.amount
}
},
actions: {
increment: ({commit}, payload) => {
commit('increment', payload)
}
}
})
在上面的代码中,我们新定义了一个mutation,名为increment,可接受一些额外的参数amount,以更新count变量。
我们可以在组件中派发一个mutation,来实现该操作(假设没有开启严格模式):
// MyComponent.vue
methods: {
increment () {
this.$store.commit('increment', { amount: 10 })
}
}
Action
Action是异步操作,而且可以包含任意异步操作。Action提供给你一个使用异步请求更新状态的方法,并且可以保证该过程是同步的。
Action利用mutation中commit的概念。Action通过store.dispatch方法异步的提交mutation,最终改变state状态。通常Action将服务端请求得到的数据提交给Mutation,成功处理一些业务逻辑后通过Mutation更新State中的状态。
// store.js
export default new Vuex.Store({
state: {
count: 0
},
mutations: {
increment: (state, payload) => {
state.count += payload.amount
}
},
actions: {
incrementAsync ({commit}, payload) {
setTimeout(() => {
commit('increment', payload)
}, 1000)
}
}
})
在上面的代码中,我们新定义了一个Action,名为incrementAsync,受到payload的委托,在1秒钟后再提交该mutation。
我们可以在组件中派发一个Action,来实现该操作(假设没有开启严格模式):
// MyComponent.vue
methods: {
incrementAsync () {
this.$store.dispatch('incrementAsync', { amount: 10 })
}
}
Vuex的核心概念
Store
Store是一个容器,它包含着应用中的所有状态。一个Vuex的Store是由唯一的一个store实例来管理的。
State
State就是存储在Store中的状态数据,State机制遵循源流驱动所提出的思想——即State可以作为源流数据,而对该数据的更新只能通过Action来派发Mutation,进而同步改变State的状态。
Getter
Getter是对State的派生数据,类似于Vue模板中的computed计算属性。Getter常作为模板中computed属性的依赖源。
Mutation
Mutation是同步的改变State中数据的唯一方法。在Mutation中建议只处理简单的动作,这种处理方式可以更容易地跟踪代码的变化。Mutation通过一系列类型名来更新State中的数据。
Action
Action允许更改State的异步数据或更复杂的逻辑,使Action中包含的异步操作可以访问到State并且可以派发Mutation。同时Action的Promise也可以在组件内使用。
Module
Module允许我们将一些较大状态的数据重构为一些具有独立功能的小模块,每个Module具有自己的State、Getter、Mutation和Action。这样,即使应用的状态不断变化或者持续增加,整个代码库也能保持整洁和可维护性。
Vuex实现示例
在Vue项目中使用Vuex非常方便,以下是其中两个示例。
示例一:计数器
// store.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: {
increment: ({ commit }) => commit('increment'),
decrement: ({ commit }) => commit('decrement')
}
})
<!-- Counter.vue -->
<template>
<div>
<h1>Count: {{$store.state.count}}</h1>
<button @click="$store.dispatch('increment')">+1</button>
<button @click="$store.dispatch('decrement')">-1</button>
</div>
</template>
<script>
export default {
name: 'Counter'
}
</script>
示例二:待办事项
// store.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
todos: [
{ id: 1, text: 'todo1', done: true },
{ id: 2, text: 'todo2', done: false }
]
},
getters: {
doneTodos: state => {
return state.todos.filter(todo => todo.done)
}
},
mutations: {
toggle: (state, id) => {
const todo = state.todos.find(todo => todo.id === id)
todo.done = !todo.done
},
add: (state, todo) => {
state.todos.push(todo)
}
},
actions: {
toggle: ({commit}, id) => {
commit('toggle', id)
},
add: ({commit}, text) => {
const todo = {
id: Date.now(),
text,
done: false
}
commit('add', todo)
}
}
})
<!-- TodoList.vue -->
<template>
<div>
<ul>
<li v-for="todo in $store.state.todos" :key="todo.id">
<span :class="{ done: todo.done }">{{ todo.text }}</span>
<button @click="$store.dispatch('toggle', todo.id)">Toggle</button>
</li>
</ul>
<input type="text" v-model="text">
<button @click="$store.dispatch('add', text)">Add</button>
</div>
</template>
<script>
export default {
name: 'TodoList',
data() {
return {
text: ''
}
},
mounted() {
console.log(this.$store.getters.doneTodos)
}
}
</script>
<style>
.done { text-decoration: line-through; }
</style>
结论
Vuex是Vue.js的状态管理插件,可以有效地帮助我们管理应用程序的状态,在使用中体现了源流驱动的思想、模块化的技术手段、设计模式上的优化,其实现机制基于State、Getter、Mutation和Action四个核心概念,可以帮助前端工程师更加规范化、系统化地管理自己的前端代码,提高工作效率。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Vue详细讲解Vuex状态管理的实现 - Python技术站