vuex为咱们提供了两种使用方法vue
vuex下载地址:https://unpkg.com/vuex@2.0.0 es6
下载以后用< script >标签包裹引入便可vuex
npm install vuex --save
在一个模块化的打包系统中,您必须显式地经过 Vue.use() 来安装 Vuex:shell
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex)
当使用全局 script 标签引用 Vuex 时,不须要以上安装过程。npm
vuex就是一个状态(数据)管理工具,每个vuex都有一个store(仓库),store是一个容器,它包含着你的应用中大部分的状态(state)。Vuex 和单纯的全局对象有如下两点不一样:异步
1.Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地获得高效更新。模块化
2.你不能直接改变 store 中的状态。改变 store 中的状态的惟一途径就是显式地提交(commit) mutations。这样使得咱们能够方便地跟踪每个状态的变化,从而让咱们可以实现一些工具帮助咱们更好地了解咱们的应用。函数
建立vuex工具
var store = new Vuex.store({ // 数据放在state中 state:{ msg:1 }, // 新建方法 mutations:{ // es6 写法 jia(state){ state.msg++ } } }) // 调用mutation中的"jia"方法 store.commit("jia") // 查看数据状态 console.log(store.state.msg)
再次强调,咱们经过提交 mutation 的方式,而非直接改变 store.state.count,是由于咱们想要更明确地追踪到状态的变化。这个简单的约定可以让你的意图更加明显,这样你在阅读代码的时候能更容易地解读应用内部的状态改变。此外,这样也让咱们有机会去实现一些能记录每次状态改变,保存状态快照的调试工具。有了它,咱们甚至能够实现如时间穿梭般的调试体验。测试
上面咱们已将vuex建立,那么如何在组件中进行使用呢?
咱们只须要在组件中利用计算属性rutern出store.state.msg便可,触发变化也只是在methods里面提交mutation.
var vm = new Vue({ el:"#box" components:{ home:{ computed:{ msg(){ return store.state.msg } }, template:` <div> {{msg}} <input type="button" @click="jia" value="+"/> </div>`, methods:{ jia:function(){ store.commit("jia") } } } } })
Vuex 使用 单一状态树 —— 是的,用一个对象就包含了所有的应用层级状态。至此它便做为一个『惟一数据源(SSOT)』而存在。这也意味着,每一个应用将仅仅包含一个 store 实例。单一状态树让咱们可以直接地定位任一特定的状态片断,在调试的过程当中也能轻易地取得整个当前应用状态的快照。
单状态树和模块化并不冲突 —— 在后面的章节里咱们会讨论如何将状态和状态变动事件分布到各个子模块中。
computed:{ msg(){ return store.state.msg } },
由于咱们在根实例已经注册了store,因此咱们也可使用这种写法
computed:{ msg(){ return this.$store.state.msg } },
这样咱们在模块化的构建系统中,在每一个须要使用 state 的组件中就不须要频繁地导入,而且在测试组件时不须要模拟状态。
当一个组件须要获取多个状态时候,将这些状态都声明为计算属性会有些重复和冗余。为了解决这个问题,咱们可使用 mapState 辅助函数帮助咱们生成计算属性,让你少按几回键:
computed: mapState({ // 箭头函数可以使代码更简练 msg: state => state.msg, })
mapState 函数返回的是一个对象。咱们如何将它与局部计算属性混合使用呢?
对象展开运算符能够将mapstate与局部计算属性混合使用
computed: { localComputed () { /* ... */ }, // 使用对象展开运算符将此对象混入到外部对象中 ...mapState({ // ... }) }
使用 Vuex 并不意味着你须要将全部的状态放入 Vuex。虽然将全部的状态放到 Vuex 会使状态变化更显式和易调试,但也会使代码变得冗长和不直观。若是有些状态严格属于单个组件,最好仍是做为组件的局部状态。你应该根据你的应用开发须要进行权衡和肯定。
getters能够说是store的计算属性,它能够接受state做为第一参数和其余getters做为第二参数来进行计算,这样咱们就能够在多个组件使用这个gtters而没必要在每个组建都书写一遍.
var store = new Vuex.store({ // 数据放在state中 state:{ msg:1 }, // 新建方法 mutations:{ // es6 写法 jia(state){ state.msg++ } }, getters:{ jiajia(state){ state.msg+5 } } })
computed: { // 使用对象展开运算符将 getters 混入 computed 对象中 ...mapGetters([ 'jiajia', ]) }
更改 Vuex 的 store 中的状态的惟一方法是提交 mutation。Vuex 中的 mutations 很是相似于事件:每一个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是咱们实际进行状态更改的地方,而且它会接受 state 做为第一个参数:
mutations:{ // es6 写法 jia(state){ state.msg++ } },
你能够向 store.commit 传入额外的参数,即 mutation 的 载荷(payload):
mutations: { increment (state, n) { state.msg += n } }
提交 mutation 的另外一种方式是直接使用包含 type 属性的对象:
store.commit({ type: 'increment', amount: 10 })
当使用对象风格的提交方式,整个对象都做为载荷传给 mutation 函数,所以 handler 保持不变:
mutations: { increment (state, payload) { state.msg += payload.amount } }
Action 相似于 mutation,不一样在于:
Action 提交的是 mutation,而不是直接变动状态。
Action 能够包含任意异步操做。
让咱们来注册一个简单的 action:
const store = new Vuex.Store({ state: { count: 0 }, mutations: { increment (state) { state.count++ } }, actions: { increment (context) { context.commit('increment') } } })
Action 函数接受一个与 store 实例具备相同方法和属性的 context 对象,所以你能够调用 context.commit 提交一个 mutation,或者经过 context.state 和 context.getters 来获取 state 和 getters。当咱们在以后介绍到 Modules 时,你就知道 context 对象为何不是 store 实例自己了。
实践中,咱们会常常用到 ES2015 的 参数解构 来简化代码(特别是咱们须要调用 commit 不少次的时候):
actions: { increment ({ commit }) { commit('increment') } }