vuex 使用

# vuex 使用

# Vuex 是什么?

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex 也集成到 Vue 的官方调试工具 devtools extension,提供了诸如零配置的 time-travel 调试、状态快照导入导出等高级调试功能。

# 什么是“状态管理模式”?

让我们从一个简单的 Vue 计数应用开始:

new Vue({
  // state
  data() {
    return {
      count: 0,
    };
  },
  // view
  template: `
    <div>{{ count }}</div>
  `,
  // actions
  methods: {
    increment() {
      this.count++;
    },
  },
});

# 什么情况下我应该使用 Vuex?

Vuex 可以帮助我们管理共享状态,并附带了更多的概念和框架。这需要对短期和长期效益进行权衡。

如果您不打算开发大型单页应用,使用 Vuex 可能是繁琐冗余的。确实是如此——如果您的应用够简单,您最好不要使用 Vuex。一个简单的 store 模式就足够您所需了。但是,如果您需要构建一个中大型单页应用,您很可能会考虑如何更好地在组件外部管理状态,Vuex 将会成为自然而然的选择。

# 开始

# 手摸手教你学会如何使用 Vuex

  • 1、下载安装:npm install vuex --save
  • 2、创建一个存储数据的仓库,为了方便管理我们可以在 src 目录下创建一个 store 目录,然后在里面创建数据仓库文件 index.js,具体代码如下:
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
//不是在生产环境debug为true
const debug = process.env.NODE_ENV !== 'production';
new Vuex.Store({
  strict:debug,//在不是生产环境下都开启严格模式
  // state为驱动应用的数据源
  state: {
    city: "北京",
  },
});
export default Vuex.Store;
  • 3、我们需要将该数据仓库 import 到 main.js 中使关键字“store”成为全局能使用的 API,具体代码如下:
import Vue from 'vue'
import App from './App'
import router from './router'
import store from './store/index'
Vue.config.productionTip = false/* eslint-disable no-new */new Vue({
  el: '#app',
  router,
  store,
  components: { App },
  template: '<App/>'})
  • 4、由于我们在 main.js 将 store 这个玩意加载到了 new Vue 实例中,因此我们要在组件中调用数据仓库中存储的数据那就十分简单,下面看示例代码:
<div class="header-right">
   {{this.$store.state.city}}</div>
  • 以上就是基础的 vuex 使用方式,下面我们需要实现的触发某事件,然后数据发生变化的操作,在开始看具体之前,先来琢磨一下官方给出的这张数据流向图: 结合这张图我们可知在组件中的数据是通过 dispatch 这个方法传递出去,核心代码实现如下:
//HTML代码,定义一个方法,在方法中派发一个changeCity事件,并传递参数<div class="title border-bottom">热门城市</div><div class="button-list">
  <div class="button-wrapper" v-for="item of hot" :key="item.id" @click="handleCityClick(item.name)">
    <div class="button">{{item.name}}</div>
  </div></div>//Vue实例代码,通过dispatch派发成一个事件,并接收传值然后再传出去methods: {
  handleCityClick (city) {
    this.$store.dispatch('changeCity', city)
    this.$router.push({
      path: '/'
    })
  }}

继续看官网的数据流向图,可以知道此时数据来到了存储数据的仓库,此时的代码如下:

import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
new Vuex.Store({
  state: {
    city: "上海",
  },
  actions: {
    //ctx参数代表上下文,与mutations进行通信,city是组件传递过来的数据
    //commit()方法的作用是将city数据传递给MchangeCity这个方法
    changeCity(ctx, city) {
      ctx.commit("MchangeCity", city);
    },
  },
});
export default Vuex.Store;
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
new Vuex.Store({
  state: {
    city: "上海",
  },
  actions: {
    changeCity(ctx, city) {
      ctx.commit("MchangeCity", city);
    },
  },
  mutations: {
    //state代表了最开始存放的区域,即驱动应用的数据源
    MchangeCity(state, city) {
      state.city = city;
    },
  },
});
export default Vuex.Store;

虽然以上就是完整的实现了组件之间数据联动的功能,但是事情还没结束呢,因为刷新页面时,数据还是会变回 state 中最初始的值,那么该怎么办呢?此时,就到了 HTML5 中的 localstorage 大显神威的时候了!下面请看具体代码,简直太简单了:

import Vue from 'vue'import Vuex from 'vuex'Vue.use(Vuex)export default new Vuex.Store({
  state: {
    city: localStorage.city || '上海'
  },
  actions: {
    changeCity (ctx, city) {
      ctx.commit('MchangeCity', city)
    }
  },
  mutations: {
    MchangeCity (state, city) {
      state.city = city
      localStorage.city = city    }

为了避免用户将浏览器的本地存储关闭而导致的错误使网站奔溃,我们应该编写以下更加合理的代码:

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
let defaultcity = '上海'try {
  if (localStorage.city) {
    defaultcity = localStorage.city  }} catch (e) {}export default new Vuex.Store({
  state: {
    city: defaultcity  },
  actions: {
    changeCity (ctx, city) {
      ctx.commit('MchangeCity', city)
    }
  },
  mutations: {
    MchangeCity (state, city) {
      state.city = city      try {
        localStorage.city = city      } catch (e) {}
    }
  }})
  export {defaultcity}

其实对于 vuex 数据的传递,我们还有一个简洁的方法,就是定义一个数组项来映射 vuex 中的数据,使 HTML 代码中调用数据的代码量减少,同时方便管理,下面看具体代码:

<!-- {{this.$store.state.city}}变成了this.city -->
<div class="header-right">
   {{this.city}}</div><script>import { mspState } from 'vuex'export default {
  name: 'HomeHeader',
  computed: {
    ...mapState(['city'])
  }}</script><script>//我们也能传递个对象过去//此时this.city就要变成this.currentCity了import { mspState } from 'vuex'export default {
  name: 'HomeHeader',
  computed: {
    ...mapState({
      currentCity: 'city'
    })
  }}</script>

# Vuex 中跳过 actions 的用法

我们在应用 vuex 的时候还可以将 actions 这个步骤直接忽略掉,使代码变得更加简洁

// 组件代码
let status = sessionStorage.getItem("systemStatus");
this.$store.commit('systemSta', status);
// vuex文件代码
state: {
  systemStatus: ""},
  mutations: {
  systemSta(state, value) {
    state.systemStatus = value;
  }
 }
// 另一个组件代码
let status = this.$store.state.systemStatus;

以上关于 Vuex 的内容整理几乎都是大白话式的,为了更好的深入理解和学习 Vuex,请立刻前来官方网站

# 辅助函数:

  • 引入辅助函数,从同一个库中引入多个的时候使用大括号
  • 大括号里面的没有顺序之分

# 使用步骤

1:导入
import {mapState,mapGetters,mapActions,mapMutations} from 'vuex'

2:store文件夹中的index.js 文件中

export default new Vuex.Store({
    state:{
        count:0,
        num:100
    },
    getters:{
        changeState(state){
            return state.count/4
        }
    },
    actions:{
        acCountAdd({commit},val){
            commit('muCountAdd',val)
        },
        acCountMinus({commit},val){
            commit('muCountMinus',val)
        },
    },
    mutations:{
        muCountAdd(state,val){
            state.count+=val
        },
        muCountMinus(state,val){
            state.count-=val
        }
    },
})

3:组件内写法
computed:{
    // 使用state辅助函数,使用对象方式时,名称可以不一致
    ...mapState({
      count:state=>state.count
    }),
    // 使用getters辅助函数,使用对象方式时,名称可以不一致
    ...mapGetters({
      changeState:'changeState'
    })
  },
methods: {
    // 使用mutations辅助函数,使用对象方式时,名称可以不一致
    ...mapMutations({
      muCountAdd:'muCountAdd'
    }),
    // 使用actions辅助函数,使用对象方式时,名称可以不一致
    ...mapActions({
      acCountAdd:'acCountAdd'
    })
},
 
辅助函数:mapState,mapGetters,mapActions,mapMutations

	1.mapState:映射state中的数据到this.data上,
	vuex的state,getters,使用辅助函数映射过来要放在computed中
	写法:...mapState([]),映射的每一条数据都是字符串
	...mapState({,穿对象的时候能给映射的数据起别名
	别名:箭头函数的返回值就是别名的值,state作为参数的函数返回值
	})
	2.mapGetters:映射getters中的数据到this.data上
	写法:...mapGetters([]),不需要起别名的时候数组作为参数,把映射过来的数据作为数组中的字符串
	...mapGetters({}),需要起别名的时候对象作为参数,对象中的key是别名,value是原名,原名是字符串

	3.mapActions:映射actions中的函数到组件的methods上
	mapActions,mapMutations映射过来的函数放在methods中
	写法:...mapActions([]),参数为数组的时候不能起别名,函数名作为参数数组的每一项
	...mapActions({
	key:value   key是别名,value是原名,原名是字符串
	})
	4.mapMutations:把mutations中的函数映射到methods中
	写法:...mapMutations([]),参数为数组的时候不能起别名,数组里面的每一项都是函数名字符串
	...mapMutations({
	key:value  key是别名,value是原名
	})