[TOC] ------- ## Vuex起步 每一个 Vuex 应用的核心就是 store(仓库)。 "store" 基本上就是一个容器,它包含着你的应用中大部分的状态(state)。 Vuex 和单纯的全局对象有以下两点不同: - Vuex 的状态存储是响应式的。 当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。 - 你不能直接改变 store 中的状态。 改变 store 中的状态的唯一途径就是显式地提交(commit) mutations。 这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。 ### 最简单的 Store 假设一个微小的应用,有一个标签显示数字,两个按钮分别做数字的加一和减一的操作。用户界面看起来是这样的: ![](https://box.kancloud.cn/77d8861431c128f12b97b3e92c1ae2fa_114x29.png) 使用vue的话,就是这样: ~~~ <script src="https://unpkg.com/vue/dist/vue.js"></script> <div id="app"> <p>{{count}} <button @click="inc">+</button> <button @click="dec">-</button> </p> </div> <script> new Vue({ el:'#app', data () { return { count: 0 } }, methods: { inc () { this.count++ }, dec () { this.count-- } } }) </script> ~~~ >[success]预览: 整个代码结构非常清晰,代码是代码,数据是数据。代码就是放在methods数组内的两个函数inc、dec,被指令@click关联到button上。而data内返回一个属性count,此属性通过{{count}}绑定到标签p内。 现在来看看,同样的demo app,使用vuex完成的代码的样子 安装 Vuex 之后,让我们来创建一个 store。创建过程直截了当——仅需要提供一个初始 state 对象和一些 mutations: ~~~ <script src="https://unpkg.com/vue/dist/vue.js"></script> <script src="https://unpkg.com/vuex@2.0.0"></script> <div id="app"> <p>{{count}} <button @click="inc">+</button> <button @click="dec">-</button> </p> </div> <script> // 如果在模块化构建系统中,请确保在开头调用了 Vue.use(Vuex) const store = new Vuex.Store({ state: { count: 0 }, mutations: { inc: state => state.count++, dec: state => state.count-- } }) const app = new Vue({ el: '#app', computed: { count () { return store.state.count } }, methods: { inc () { store.commit('inc') }, dec () { store.commit('dec') } } }) </script> ~~~ >[success]预览: 我们先看到有哪些重要的变化: - 新的代码添加了对vuex脚本的依赖。这是当然的,因为你需要使用vuex的技术,当然需要引用它 - methods数组还是这两个方法,这和demo1是一样的;但是方法内的计算逻辑,不再是在函数内进行,而是提交给store对象!这是一个新的对象! - count数据也不再是一个data函数返回的对象的属性;而是通过计算字段来返回,并且在计算字段内的代码也不是自己算的,而是转发给store对象。再一次store对象! 就是说,之前在vue实例内做的操作和数据的计算现在都不再自己做了,而是交由对象store来做了。 store对象是Vuex.Store的实例。 在store内有分为state对象和mutations对象,其中的state放置状态,mutations则是一个会引发状态改变的所有方法。 正如我们看到的,目前的state对象,其中的状态就只有一个count。 而mutations有两个成员,它们参数为state,在函数体内对state内的count成员做加1和减1的操作。 再次强调,我们通过提交 mutation 的方式,而非直接改变 store.state.count,是因为我们想要更明确地追踪到状态的变化。这个简单的约定能够让你的意图更加明显,这样你在阅读代码的时候能更容易地解读应用内部的状态改变。此外,这样也让我们有机会去实现一些能记录每次状态改变,保存状态快照的调试工具。有了它,我们甚至可以实现如时间穿梭般的调试体验。 由于 store 中的状态是响应式的,在组件中调用 store 中的状态简单到仅需要在计算属性中返回即可。触发变化也仅仅是在组件的 methods 中提交 mutations。