Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
状态管理模式
一个状态自管理应用包含以下几个部分:state,驱动应用的数据源;
view,以声明方式将 state 映射到视图;
actions,响应在 view 上的用户输入导致的状态变化。
当我们的应用遇到多个组件共享状态时,单向数据流的简洁性很容易被破坏:
多个视图依赖于同一状态。
不同视图需要变更同一状态。
所以状态管理模式就是把共享的状态提取出来,在一个全局的地方进行统一管理。不管组件在哪,都能触发行为、获取状态,提高了代码维护性。
原理简单理解
Vuex 实现了一个单向数据流,全局管理 state 状态树,组件通过派发 Dispatch 一个 action,action 也是无法直接修改State的,还是需要通过 Mutation来修改State的数据。action 进行 commit 并调用 Mutations 方法来更改 state,Mutation同时提供了订阅者模式供组件调用获取State数据的更新。最后根据 state 的变化触发视图的更新。Vue Components:Vue组件。
dispatch:是唯一能执行action的方法。
actions:由组件 dispatch 触发。然后由commit()来触发mutation的调用 , 更新 state。
commit:状态改变提交操作方法。对mutation进行提交,是唯一能执行mutation的方法。
mutations:状态改变操作方法,由actions中的commit('mutation 名称')来触发。该方法只能进行同步操作,且方法名只能全局唯一。
state:页面状态管理容器对象。
实践 - 城市选择
实现一个常见的城市选择页面。包含首页和城市选择页。
新建一个 IndexPage.vue
// IndexPage.vue
<template>
<div>{{city}}</div>
</template>
<script>
import { mapState} from 'vuex'
export default {
name: "IndexPage",
computed: {
...mapState(['city'])
}
}
</script>
新建一个 CityPage.vue
// CityPage.vue
<template>
<div>
<p>当前城市:{{city}}</p>
<div v-for="item of ['北京','上海','广州']" :key="item">
<button @click="handleChangeCity(item)"
>{{item}}
</button>
</div>
</div>
</template>
<script>
import { mapState ,mapMutations } from 'vuex'
export default {
name: "CityPage",
computed: {
...mapState(['city'])
},
methods: {
...mapMutations(['changeCity']),
handleChangeCity (city) {
this.changeCity(city)
},
},
}
</script>
在 App.vue 中加入这两个页面。
// App.vue
<template>
<div>
<IndexPage/>
-----------
<CityPage/>
</div>
</template>
<script>
import IndexPage from './pages/IndexPage'
import CityPage from './pages/CityPage'
export default {
name: 'App',
components: {
IndexPage,
CityPage
}
}
</script>
接下来重点来了,src 里 新建一个 store 文件夹 (如果使用脚手架搭建的就已经有这个文件夹了)。
store 文件夹下新建一个 index.js ,别忘了注入到 main.js。
// index.js
import Vue from 'vue'
import Vuex from 'vuex'
import state from './state'
import mutations from './mutations'
import actions from './actions'
Vue.use(Vuex)
export default new Vuex.Store({
state,
actions,
mutations
})
新建一个 state.js
// state.js
let defaultCity = '全国'
try {
if (localStorage.city) {
defaultCity = localStorage.city
}
} catch (e) {
}
export default {
city: defaultCity
}
新建一个 actions.js
// actions.js
export default {
changeCity (context, city) {
context.commit('changeCity', city)
}
}
新建一个 mutations.js
// mutations.js
export default {
changeCity (state, city) {
state.city = city
try {
localStorage.city = city
} catch (e) {
}
}
}
完成后如下图所示。选择新的城市,首页和城市选择页里的 city 会同步更新。