Alex-Programer

Alex-Programer

随缘博客,不定期更新不确定的内容~
github
twitter

Vuex 基本使用

官方定义#

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

注入 vuex#

import store from "./store";

new Vue({
  store,
});

store.js

import Vue from "vue";
import Vuex from "vuex";

Vue.use(Vuex);

export default new Vuex.Store({
  state: {
    msg: "hello world",
  },
  mutations: {},
  actions: {},
});

获取状态#

这样在任何一个组件里,都可以这样获取到这个 msg

<template>
  <div class="about">
    <h1>This is an about page</h1>
    <h2>{{$store.state.msg}}</h2>
  </div>
</template>

修改状态#

mutations 提供一个修改状态的方法

mutations: {
  setMsg(state, newMsg) {
    state.msg = newMsg
  }
}

再让 actions 来提交修改的请求

actions: {
  setMsg ({ commit }) {
    commit('setMsg', 'hello')
  }
}

修改的动作,在其它组件里去触发

<template>
  <div class="about">
    <h1>This is an about page</h1>
    <h2>{{$store.state.msg}}</h2>
  </div>
</template>

<script>
export default {
  mounted () {
    this.$store.dispatch('setMsg')
  }
}
</script>

思考#

上例属于简单的状态管理,state 在存放状态、mutations 提供了修改状态的方法、actions 负责触发修改状态的方法,并提交修改的数据;上例 actions 里是手动修改的数据,工作中应该是提交请求的数据。但是上例中有个明显的问题,谁都可以修改(dispatch)状态。

命名空间#

如果项目足够复杂,那么可以使用 vuex 提供的命名空间来修改状态。使用的前提还需要使用 vuexmodulesmodules是个对象,其结构也是由statemutationsactions组成。区别是它多了一个namespaced 属性,以此来使用命名空间。

修改状态的三种方法#

dispatch#

先把原来写的内容提取到一个 modules

store.js

import Vue from "vue";
import Vuex from "vuex";
import home from "./modules/home";

Vue.use(Vuex);

export default new Vuex.Store({
  modules: {
    home,
  },
});

./modules/home.js

export default {
  namespaced: true,
  state: {
    msg: "hello world",
  },
  actions: {
    setMsg({ commit }) {
      commit("setMsg", "hello");
    },
  },
  mutations: {
    setMsg(state, newMsg) {
      state.msg = newMsg;
    },
  },
};

最后取状态和修改状态

<template>
  <div class="about">
    <h1>This is an about page</h1>
    <h2>{{$store.state.home.msg}}</h2>
  </div>
</template>

<script>
export default {
  mounted () {
    this.$store.dispatch('home/setMsg')
  }
}
</script>

观察最后修改时和之前的不同,无非是取状态和修改状态都多了一层 home ,提高了一定的使用门槛。尽管这样,但至少可以识别操作的是哪个模块的状态。

上例再通过 modules 修改 状态还有另一种等价的写法

mapActions#

<template>
  <div class="about">
    <h1>This is an about page</h1>
    <h2>{{$store.state.home.msg}}</h2>
  </div>
</template>

<script>
import { mapActions } from 'vuex'

export default {
  methods: {
    ...mapActions('home', ['setMsg'])
  },
  mounted () {
    this.setMsg()
  }
}
</script>

mapActions 执行完后返回的是一个对象,通过扩展运算法展开后,会在当前实例里添加一个 setMsg 方法。调用这个方法就会触发状态的修改。

createNamespacedHelpers#

上面两个方法都有一个很明显的问题,如果在当前组件里,需要修改的状态有很多个。那么就意味着有很多层 home。通过 vuexcreateNamespacedHelpers 方法,可以很友好的解决这个问题。

<template>
  <div class='about'>
    <h1>This is an about page</h1>
    <h2>{{$store.state.home.msg}}</h2>
  </div>
</template>

<script>
import { createNamespacedHelpers } from 'vuex'
const { mapActions } = createNamespacedHelpers('home')

export default {
  methods: {
    ...mapActions(['setMsg'])
  },
  mounted () {
    this.setMsg()
  }
}
</script>

简化取值#

之前的例子一直没有提到取值的问题,实际工作中也不推荐那么去做;vuex 提供了一个 mapState 的方法,可以简化取值。

<template>
  <div class='about'>
    <h1>This is an about page</h1>
    <h2>{{msg}}</h2>
  </div>
</template>

<script>
import { createNamespacedHelpers } from 'vuex'
const { mapActions, mapState } = createNamespacedHelpers('home')

export default {
  computed: {
    ...mapState(['msg'])
  },
  methods: {
    ...mapActions(['setMsg'])
  },
  mounted () {
    this.setMsg()
  }
}
</script>

提取变量#

回忆一下 setMsg 这个字眼出现的次数,在组件里使用出现过,在 storemodules 里出现过。这时提倡的做法,就是将这个 setMsg 提取出来,用一个常量保存;

./store/action-type.js

export const SET_MSG = "setMsg";

使用的时候,尽量避免直接使用 setMsg,这样便于自己或其他人去维护。

总结#

vuex 的便利性不言而喻,根据项目的复杂度,它提供了渐进增强的方案。当项目很简单时,不用 modules 就能解决基本需求。如果复杂度上升了,modules 自然是不二选择。如果模块儿的个数并不多,大可只用 dispatch。即便模块儿多了起来,createNamespacedHelpers 也为后续工作铺好了路。

加载中...
此文章数据所有权由区块链加密技术和智能合约保障仅归创作者所有。