Vuex入门 | 三种使用方法详解

Vuex安装与初始化操作

在这里插入图片描述

安装vuex

npm install --save vuex

在main.js中引入vuex

import Vue from 'vue'
import store from './store' //引入Vuex的store

new Vue({
  el: '#app',
  store //注册上Vuex的store; 所有组件对象都多了一个属性 $store
})

然后新建store.js文件,模板如下

//vuex最和核心的管理对象store
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex);

//相当于data对象的状态对象
const state={}
//包含了n个直接更新状态的方法的对象
const mutations={}
//包含了n个间接更新状态的方法的对象,action的请求是提交给mutations的
const actions={  }
//包含多个getter计算属性对象
const getters={ }
//Store为大写
//小写的话报错 Uncaught TypeError: __WEBPACK_IMPORTED_MODULE_1_vuex__.a.store is not a constructor
export default new Vuex.Store({ state, mutations, actions, getters})

store对象属性

在这里插入图片描述

Vuex 三种使用方式

方式一:一个文件管理Vuex

需求一:点击’+'按钮,对数字加一

在这里插入图片描述

代码结构:

在这里插入图片描述

Counter.Vue

<template>
  <div>
    <p>click {{count}} times, count is {{evenOrOdd}}</p>
    <button @click="increment">+</button>
  </div>
</template>
  1. 首先需要将需要管理的状态 count 在store中进行管理,在store.js 中的state中添加count属性

store.js

//相当于data对象的状态对象
const state={
 	count:0   //指定初始化数据
}
  1. 接着,需要将@click="increment"所需要的方法写出
<template>
  <div>
    <p>click {{count}} times, count is </p>
    <button @click="increment">+</button>
  </div>
</template>

<script>
  export default {
    methods: {
      increment () {
        this.$store.dispatch('increment') //调用action中的increment方法来进行数据操作
        }
  }
</script>

  1. 写出相对应的action与mutation
//包含了n个间接更新状态的方法的对象,action的请求是提交给mutations的
const actions={
  increment({commit}){commit('INCREMENT') } //提交一个mutation请求
}
//包含了n个直接更新状态的方法的对象
const mutations={ INCREMENT(state){state.count++;}
}

Action 与 mutation的区别

  • Action提交的是mutation,而不是直接变更状态
  • Action 可以包含任意异步操作,比如axios 异步请求
actions: {
    increment (context) {
      context.commit('increment')
    }
  }

Action 函数接收一个与store实例具有相同方法和属性的context对象,因此可以调用 context.commit 提交一个 mutation, 或者通过 context.state 和 context.getters 来获取state 和getters。

但是在实际使用中,经常会用ES5参数解构来简化代码,于是就经常这样写

actions: {
  increment ({ commit }) {  // let {commit}= context相当于 let commit= context.commit
    commit('increment')
  }
}

需求二:点击’+'按钮,对数字加减之后,需要显示出这个数是偶数还是奇数

在这里插入图片描述

  1. 此要求,需要在count基础之上,对count进行属性计算操作,先通过Vuex获取所定义的计算属性
<p>click {{count}} times, count is {{evenOrOdd}}</p>
<script>
  export default {
       computed: {
          evenOrOdd () {
            return this.$store.getters.evenOrOdd
          }
    },
  }
</script>
  1. 在store.js中的getters中填写相对应的计算属性
//包含多个getter计算属性对象
const getters={
  evenOrOdd(state){//当读取属性值时自动调用并返回属性值
    return state.count % 2 === 0 ? '偶数' : '奇数';
  }
}

Getter 计算属性

Vuex 允许我们在 store 中定义“getter”(可以认为是 store 的计算属性)。就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。

通过Vuex辅助函数简化操作

<template>
  <div>
    <p>click {{count}} times, count is {{evenOrOdd}}</p>

    <button @click="increment">+</button>
    <button @click="decrement">-</button>
  </div>
</template>

<script>
  import {mapState, mapGetters, mapActions} from 'vuex'

  export default {
    /*computed: {
      count () {return this.$store.state.count},
      evenOrOdd () {return this.$store.getters.evenOrOdd}
    },*/
    computed: {
      ...mapState(['count']), 
      ...mapGetters(['evenOrOdd'])
    },

    /*methods: {
      increment () { this.$store.dispatch('increment')},
      decrement () { this.$store.dispatch('decrement')}
    }*/
    methods: {
      ...mapActions(['increment', 'decrement'])
    }
  }
</script>

方式二:根据功能拆分使用

也就是说,将state、mutations、actions、getters都拆分出去

拆分后,代码结构如下

在这里插入图片描述

  1. 首先需要创建index.js文件,作为入口
//Vuex核心管理模块store对象
import Vue from 'vue'
import Vuex from 'vuex'

import state from './state';
import mutations from './mutations';
import actions from './actions';
import getters from './getters';

Vue.use(Vuex);

export default new Vuex.Store({state,mutations,actions,getters})

  1. 其次,分别改造所需要的文件

state.js

//状态对象模块
export default {
  count:0   //指定初始化数据
}

getters.js

//包含多个getter计算属性对象
export default {
  evenOrOdd(state){//当读取属性值时自动调用并返回属性值
    return state.count % 2 === 0 ? '偶数' : '奇数';
  }
}

mutation-types.js 用来管理actions与mutation方法名称常量

//包含n个mutation名称常量
export const INCREMENT = 'increment' // 添加
export const DECREMENT = 'decrement' // 减少

actions.js

//包含了n个间接更新状态的方法的对象,action的请求是提交给mutations的
import {INCREMENT, DECREMENT} from './mutation-types'

export default {
  increment({commit}) {commit(INCREMENT)}, //提交一个mutation请求
  decrement({commit}) {commit(DECREMENT)},
}

mutations.js

//包含了n个直接更新状态的方法的对象
import {INCREMENT, DECREMENT} from './mutation-types'

export default {
  [INCREMENT](state) {
    state.count++;
  },
  [DECREMENT](state) {
    state.count--;
  }
}

方式三:按对象模块进行拆分

在这里插入图片描述

需求:需要操作两个对象,分别是 count,countTwo

当需要管理的对象多的时候,就可以将状态对象进行模块化拆分,结构如下

在这里插入图片描述

countcountTwo分别用number.jsnumber-two.js来进行管理

  1. 首先对stroe的index.js文件进行修改,引入numbernumber_two模块
//Vuex核心管理模块store对象
import Vue from 'vue'
import Vuex from 'vuex'

import number from './modules/number';
import number_two from './modules/number-two';

Vue.use(Vuex);

export default new Vuex.Store({
  modules:  //引入number 与 number_two两个模块
    number,
    number_two
  }
})
  1. number.jsnumber-two.js两个模块都可看作单独的模块

number.js

import {INCREMENT, DECREMENT} from '../mutation-types'

const state = {count:0}//指定初始化数据

const mutations = {
  [INCREMENT](state) { state.count++;},
  [DECREMENT](state) {state.count--;}
}

const actions = {
  increment({commit}) {commit(INCREMENT) },//提交一个mutation请求
  decrement({commit}) {commit(DECREMENT)},
}

const getters = {
   //当读取属性值时自动调用并返回属性值
  evenOrOdd(state){return state.count % 2 === 0 ? '偶数' : '奇数'; }
}
export default { state, mutations,actions,getters}

number-two.js

import {INCREMENT_TWO, DECREMENT_TWO} from '../mutation-types'

const state = {count:0   }//指定初始化数据

const mutations = {
  [INCREMENT_TWO](state) {state.count++;},
  [DECREMENT_TWO](state) { state.count--;}
}

const actions = {
  increment_two({commit}) { commit(INCREMENT_TWO)},//提交一个mutation请求
  decrement_two({commit}) { commit(INCREMENT_TWO)},
}

const getters = {
  evenOrOddTwo(state){return state.count % 2 === 0 ? '偶数' : '奇数';}
}

export default {state,mutations,actions,getters}

  1. 在调用属性时需要注意取值的方式

在没分模块之前想要取得state值与state计算属性,需要如下操作

 computed: {
      count() {
        return this.$store.state.number.count;
      }evenOrOdd() {
        return this.$store.getters.evenOrOdd
      },
    },

当分模块之后,取值方式就有变化了,需要添加上模块的路径

而取值计算属性与action等操作不变

 computed: {
      countTwo() {
        return this.$store.state.number_two.count;//state后加上模块名
      },
      evenOrOddTwo() {
        return this.$store.getters.evenOrOddTwo
      }
    },

版权声明:本文为qq_39150356原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。