1.Vuex介绍:
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。简单地说,Vuex 就是管理组件之间数据通信的容器,此处的组件通信是 Vue 里面所有组件,而不仅仅包括父子组件之间的通信。
2.使用案例:
1).安装:
cnpm install --save vuex |
2).在 src 目录下新建 store 目录,然后再在 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++ } } }) |
3).在 main.js 文件里面引入:
import store from './store' |
注:如果没写具体文件,引入的就是该目录下 index.js 或者 index.vue 文件。
4). 在 main.js 实例化 vue 时注入 vuex:
new Vue({ el: '#app', store, //所有子组件都将具有store的实例,子组件不再需要单独引入 components: { App }, template: '<App/>' }) |
5).在需要使用状态管理的组件里面直接使用:
<template> <div> {{ msg }} -- {{ mycount }} <button @click="clickMe" >点击我</button> </div> </template> <script> export default { name:"Hello", data(){ return { msg:'hello' } }, methods:{ clickMe : function(){ this.$store.commit('increment'); //触发状态改变 this.msg = this.$store.state.count; //在方法里面获取改变之后的值 } }, computed: { //也可以在计算属性中返回状态,更简单 mycount () { return this.$store.state.count } } } </script> |
3.Vuex 和单纯的全局对象有以下两点不同:
1). Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
2). 你不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。
4.Vuex详解:
1).State:
Vuex 使用单一状态树,而 State 作为一个状态容器的唯一数据源而存在。请确保每个要使用的状态都在 state 里面得到初始化。
2).Getter:
getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。案例:
①. 在 store/index.js 里面:
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) export default new Vuex.Store({ state: { count: 0, todos: [ { id: 1, text: '...', done: true }, { id: 2, text: '...', done: false } ] }, mutations: { increment (state) { state.count++ } }, getters: { doneTodos: state => { return state.todos.filter(todo => todo.done) } } }) |
②. 调用(Getter 会暴露为 this.$store.getters 对象):
<template> <div> {{ msg }} --{{ mycount }} <span v-for="todo in todos">{{ todo }}</span> <button @click="clickMe" >点击我</button> </div> </template> <script> export default { name:"Hello", data(){ return { msg:'hello', todos:[] } }, methods:{ clickMe : function(){ this.$store.commit('increment'); //触发状态改变 this.msg = this.$store.state.count; //在方法里面获取改变之后的值 this.todos = this.$store.getters.doneTodos; //在方法里面获取getters的值 } }, computed: { //也可以在计算属性中返回状态,更简单 mycount () { return this.$store.state.count } } } </script> <style scoped> </style> |
3).Mutation:
①. 更改 Vuex 中状态的唯一方法是提交 mutation。你不能直接调用 mutation 里面的方法,必须使用this.$store.commit('mutation里的方法名');
②. mutation中可以传参数,一般是对象:
a.在 store/index.js 里面:
mutations: { increment (state, payload) { state.count += payload.amount } } |
b.调用的时候:
this.$store.commit('increment', { amount: 10 }) |
mutation中只能包含同步操作,如果有异步操作必须放在Action 中。
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) export default new Vuex.Store({ state: { count: 0, }, mutations: { increment (state) { state.count++ } }, actions: { increment (context) { context.commit('increment'); //转向调用mutation里面的increment方法 } } }) |
Action 通过 store.dispatch 方法触发:
this.$store.dispatch('increment'); //此处调用的是action里面的increment方法 |
注:Action 提交的是 mutation,而不是直接变更状态。Action 可以包含任意异步操作。
5). 总结:我们通过提交 mutation 的方式,而非直接改变 store.state.count,是因为我们想要更明确地追踪到状态的变化。这个简单的约定能够让你的意图更加明显,这样你在阅读代码的时候能更容易地解读应用内部的状态改变。由于store中的状态是响应式的,在组件中调用 store 中的状态简单到仅需要在计算属性中返回即可。触发变化也仅仅是在组件的 methods 中提交 mutation。流程为:
view ->(dispatch) Action ->(Commit) Mutations ->(Mutate) State -> View
注意:Action不是必需品,如果有异步操作才可能用到Action,否则可以不使用。
5.Vuex使用场景:
虽然 Vuex 可以帮助我们管理共享状态,但也附带了更多的概念和框架。这需要对短期和长期效益进行权衡。如果您不打算开发大型单页应用,使用 Vuex 可能是繁琐冗余的。确实是如此——如果您的应用够简单,您最好不要使用 Vuex。一个简单的 global event bus 就足够您所需了。但是,如果您需要构建是一个中大型单页应用,您很可能会考虑如何更好地在组件外部管理状态,Vuex 将会成为自然而然的选择。