官方解释
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex 也集成到 Vue 的官方调试工具 devtools extension,提供了诸如零配置的 time-travel 调试、状态快照导入导出等高级调试功能。
状态这里泛指 vue 组件的一些当前的状况和性质,例如开发音乐播放器时,当前的播放状态是暂停、播放或者播放模式是列表循环、单曲循环,顺序播放等。
状态管理是对之前说的状态进行管理,例如 a 组件这个状态需要通知 b 组件,或者 b 组件的当前状态需要触发 b 的父组件的某个属性。
具体有以下三个内容:
view,以声明方式将 state 映射到视图;
actions,响应在 view 上的用户输入导致的状态变化
Vuex的核心
getters
mutations
actions
module
1.State
1)单一状态树
Vuex使用单一状态树--是的,用一个对象就包含了全部的应用层级状态。至此它便作为一个『唯一数据源(SSOT)』而存在。这也意味着,每个应用将仅仅包含一个store实例。单一状态树让我们能够直接地定位任一特定的状态片段,在调试的过程中也能轻易地取得整个当前应用状态的快照。
2)在Vue组件中获得Vuex状态
最好在根实例中注册store选项,该store实例会注入到根组件下的所有子组件中,且子组件能通过this.$store访问到。而不是在每个需要使用state的组件中需要频繁地导入。
3)mapState辅助函数
当一个组件需要获取多个状态时候,可以使用mapState辅助函数帮助我们生成计算属性,这样可以简化代码书写。mapState函数会返回一个对象,然后可以使用对象展开运算符将它与局部计算属性混合使用。
4)不要滥用vuex
使用Vuex并不意味着你需要将所有的状态放入Vuex。虽然将所有的状态放到Vuex会使状态变化更显式和易调试,但也会使代码变得冗长和不直观。如果有些状态严格属于单个组件,最好还是作为组件的局部状态。你应该根据你的应用开发需要进行权衡和确定。
2.Getters
getters用来从store中的state中派生出一些状态,例如对列表进行过滤并计数
getters可以认为是store的计算属性。和state类似,有mapGetters辅助函数。
所以getters的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。
3. Mutations
更改Vuex的store中的状态的唯一方法是提交mutation。Vuex中的mutations非常类似于事件:每个mutation都有一个字符串的事件类型(type)和一个回调函数(handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受state作为第一个参数
1)提交载荷(Payload)
你可以向store.commit传入额外的参数,即mutation的载荷(payload):
2)Mutations需遵守Vue的响应规则
3)使用常量替代Mutation事件类型
4)mutation必须是同步函数
5)在组件中提交Mutations
你可以在组件中使用this.$store.commit('xxx')提交mutation,或者使用mapMutations辅助函数将组件中的methods映射为store.commit调用(需要在根节点注入store)。
4. Actions
actions类似于mutation,不同在于:
actions提交的是mutation,而不是直接变更状态。
actions可以包含任意异步操作。
1)在组件中分发Action
你在组件中使用this.$store.dispatch('xxx')分发action,或者使用mapActions辅助函数将组件的methods映射为store.dispatch调用(需要先在根节点注入store)
2)组合Actions
Action通常是异步的,那么如何知道action什么时候结束呢?更重要的是,我们如何才能组合多个action,以处理更加复杂的异步流程?
首先,你需要明白store.dispatch可以处理被触发的action的回调函数返回的Promise,并且store.dispatch仍旧返回Promise。
5. Modules
由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store对象就有可能变得相当臃肿。
为了解决以上问题,Vuex允许我们将store分割成模块(module)。每个模块拥有自己的state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割。
vuex 配合 axios 开发(案例)
1.安装vuex
npm install vuex --save复制代码
2.安装axios
npm install axios --save复制代码
3.创建目录结构
main.js
import store from './store/index' //引入store
new Vue({
el: '#app',
router,
store,
components: { App },
template: '<App/>'
})
复制代码
注:以上代码在项目的vue初始化的时候引用并初始化,每一个vuex的核心就是一个store(仓库)。store相对于是一个容器,里面存放着你的项目中的大部分的状态。Vuex通过store选项,提供了一种机制将状态从根组件注入到每一个子组件中。通过这种注入机制,就能在子组件...vue 通过this.$store访问:
store/index.js
//我们组装模块并导出 store 的地方
import Vue from 'vue'
import Vuex from 'vuex'
import movieList from './modules/movieList'
Vue.use(Vuex);
export default new Vuex.Store({
modules: {
movieList
}
})复制代码
注:以上代码导入了vue和vuex模块,然后注册使用vuex,最后导出一个vuex的实例
store/modules/movieList.js
import * as types from '../mutation-types'
import movie from '../../api/movie'
const state = {
list: []
}
const getters = {
list: state => state.list //获取当前的list
}
const actions = {
// 获取正在上映的电影
getInTheaters({ commit }){
movie.getInTheatersMovie().then(data => {
commit(types.MOVIE_LIST, data)
})
}
}
const mutations = {
[types.MOVIE_LIST](state, data){
state.list = data.subjects; //改变当前的list
}
}
export default {
state,
getters,
actions,
mutations
}复制代码
store/mutation-types.js
export const MOVIE_LIST = 'MOVIE_LIST' // 电影列表复制代码
注:mutation-types:将常量放在单独的文件中,方便协作开发。
api/movie.js
import axios from 'axios'
export default {
// 获取电影列表信息
getInTheatersMovie(start = 0, count = 18){
return this.reqUrl(`/api/movie/in_theaters?start=${start}&count=${count}`)
},
// axios 请求
reqUrl(url){
return new Promise((resolve, reject) => {
axios.get(url).then(response => {
resolve(response.data);
})
})
}
}复制代码
组件中使用 ...vue
import {mapGetters, mapActions} from 'vuex'
export default {
computed: mapGetters({
list: 'list'
}),
methods: mapActions([
'searchMovie'
]),
mounted() {
this.$store.dispatch('getInTheaters'); //分发
}
}复制代码
注:你在组件中使用 this.$store.dispatch('xxx')
分发 action,或者使用 mapActions
辅助函数将组件的 methods 映射为 store.dispatch
调用(需要先在根节点注入 store
):