Vuex使用方法简介

237 阅读2分钟

1、为什么要使用Vuex

  • Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式,它采用集中式存储管理应用的所有组件的状态。
  • Vuex遵循“单向数据流” 理念,便于问题追踪以及提高代码可维护性。
  • Vue中多个视图依赖于同一状态时,视图间传参和状态同步 较困难,Vuex能够很好解决该问题。

2、Vuex核心概念

  • state: 保存数据状态,类似于vue的data选项
  • getters: 从state派生出的新状态,类似于vue的computed选项
  • mutations: 修改状态state
  • actions:复杂业务逻辑, 类似于mutation,不同之处在于action提交的是mutation, 并且可以包含异步操作
  • modules:模块化。将 store 分割成模块,每个模块拥有自己的 state、mutation、action、getter

这些核心概念的具体用法如下所示:

2.1、状态和状态变更:state和mutations

export default new Vuex.Store({
    state: { count: 0 },
    mutations: {
        increment(state, n = 1) {
            state.count += n;
        }
    }
})
<template>
  <div>
    <p>冲啊,扔了{{$store.state.count}}个炸弹</p>
    <button @click="add">扔一个</button>
  </div>
</template>
<script>
export default {
  methods: {
    add() {
      this.$store.commit("increment");
    }
  }
};
</script>

2.2、派生状态:getters

export default new Vuex.Store({
    getters: {
        left(state) {
            return 10 - state.count
        }
    }
})
<template>
  <div>
    <p>手榴弹还剩{{$store.getters.left}}</p>
  </div>
</template>

2.3、动作:actions

export default new Vuex.Store({
    actions: {
        incrementAsync({commit}) {
            setTimeout(() => {
                commit('increment', 1)
            }, 1000)
        }
    }
})
<template>
  <div>
    <button @click="addAsync">蓄力扔一个</button>
  </div>
</template>
<script>
export default {
  methods: {
    addAsync() {
      this.$store.dispatch("incrementAsync");
    }
  }
};
</script>

2.4、模块化:modules

将上面所有的示例按模块化的方式进行重构,完整代码如下所示:

// store/count.js
const count = {
    // 命名空间
    namespaced: true,
    state: {
        count: 0
    },
    getters: {
        left(state) {
            return 10 - state.count
        }
    },
    mutations: {
        increment(state) {
            state.count += 1
        }
    },
    actions: {
        increment({ getters, commit }) {
            // 复杂业务逻辑: 当炸弹有剩余时,才能继续扔炸弹
            if (getters.left > 0) {
                commit('add')
                return true
            }
            return false
        },
        incrementAsync({ dispatch }) {
            // 异步操作: 蓄力扔炸弹
            return new Promise(resolve => {
                setTimeout(() => {
                    resolve(dispatch('add'))
                }, 1000)
            })
        }
    },
}

export default count
// store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import count from './count'

Vue.use(Vuex)

export default new Vuex.Store({
  modules: {
    // 把count命名为bomb
    bomb: count
  }
})
<!--TestVuex.vue-->
<template>
  <div>
    <p>炸弹扔了{{$store.state.bomb.count}}个</p>
    <p>炸弹还剩{{$store.getters['bomb/left']}}个</p>
    <button @click="Throw">扔一个炸弹</button>
    <button @click="asyncThrow">蓄力扔一个炸弹</button>
  </div>
</template>

<script>
export default {
  methods: {
    async Throw() {
      const result = await this.$store.dispatch("bomb/add");
      if (!result) {
        alert("没炸弹了");
      }
    },
    async asyncThrow() {
      const result = await this.$store.dispatch("bomb/asyncAdd");
      if (!result) {
        alert("没炸弹了");
      }
    }
  }
};
</script>