vuex总结

1.vuex的具体构成关系图

169333756a0230aa.png

2.vuex的使用

2.1 创建store.js

在使用Vue CLI生成的项目时会让你选择store,选择了后会在页面给你生成一个store.js,这就是最初的store,里面结构如下:

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {

  },
  mutations: {

  },
  actions: {

  }
})
复制代码

2.2 state

Vuex的核心就是仓库store,这个store实例会被注入到所有子组件里面,里面的state属性保存着我们的状态,比如我们定义一个状态count:

export default new Vuex.Store({
  state: {
    count: 10
  },
})
复制代码

其他组件想要获取count,需要使用计算属性来获取

export default {
  data() {
    
  },
  computed: {
    count() {
      return this.$store.state.count;
    }
  }
}
复制代码

为根实例中注册 store 选项,该 store 实例会注入到根组件下的所有子组件中,且子组件能通过 this.$store 访问到。通过计算属性,我们就可以在模板里面使用模板语法来调用count了,如下:

<template>
  <div>
    <p>{{ count }}</p>
  </div>
</template>
复制代码

2.3 getter

getter就是对状态进行处理的提取出来的公共部分,当状态要进行筛选这些操作时,我们可以通过getter处理过后再返回给组件使用,比如我们在state部分定义了一个list数组:

export default new Vuex.Store({
  state: {
    list: [1, 2, 3, 4, 5, 6, 7, 8]
  },
});
复制代码

我们想要筛选出数组里面的偶数然后再在组件里面使用,那么筛选的这个工作可以放在getter里面来完成。

export default new Vuex.Store({
  state: {
    list: [1, 2, 3, 4, 5, 6, 7, 8]
  },
  getters: { //  这个主要是对状态的处理,相当于把状态处理的方法抽成公共部分来管理了
    modifyArr(state) { // 一般化getter
      return state.list.filter((item, index, arr) => {
        return item % 2 == 0;
      })
    },
    getLength(state, getter) { // 方法里面传getter,调用modifyArr来计算长度
      return getter.modifyArr.length;
    }
});
复制代码

之后再在其他组件的computed里面去调用getter来获取想要的状态
使用getter的第一种方式:

computed: {
    list() {
      return this.$store.getters.modifyArr;
    },
}
复制代码

使用getter的第二种方式:

his.$store.getters.名称
复制代码

mapGetters

mapGetters 辅助函数仅仅是将 store 中的 getter 映射到局部计算属性,当我们想在组件里面引入多个getter时,可以使用mapGetter:

import {mapGetters} from 'vuex';
复制代码

比如像刚才在在上面定义的modifyArr,getLength。我们想引入这个两个并获取其值:

computed: {
  ...mapGetter(['modifyArr', 'getLength'])
}
复制代码

你当然可以为其指定别名,不一定非得用store里面getters定义的名字:

computed: {
  mapGetter({
    arr: 'modifyArr',   // 把 `this.arr` 映射为 `this.$store.getters.modifyArr`,下面同理
    length: 'getLength'
  })
}
复制代码

如果你的computed属性包含其他计算方法,那你就只能使用展开运算符的写法,这里跟mapState有点区别,其他计算属性如果写在mapGetter里面会报错,说不存在的getter,所以用以下的写法:

computed: {
  msg() {
    return this.num * 10;
  },
  ...mapGetters([
    'modifyArr',
    'getLength'
  ])
}
复制代码

或者指定别名

computed: { 
  msg() {
    return this.num * 10;
  },
  ...mapGetters({
    getList: 'modifyArr',
    length: 'getLength'
  })
}
复制代码

复制代码然后再模板里面调用:

<template>
  <div>
    <h2>mapGetters的使用演示</h2>
    <p>你的数字:{{ msg }}</p>
    <p>你的数组长度为:{{ length }}</p>
    <ul>
      <li v-for="(item, index) in getList" :key="index">{{ item }}</li>
    </ul>
  </div>
</template>
复制代码

2.4 mutation

当我们需要修改store里面的状态时,我们不是在组件里面直接去修改它们,而是通过mutation里面的方法来进行修改,这样有利于追踪状态的改变。 比如state里面有一个count变量,我们点击加减按钮来控制它的值:

mutations: {
  add(state) {
    state.count++;
  },
  reduce(state) {
    state.count--;
  }
},
复制代码

在其他组件里面,我们通过定义methods并绑定事件来触发改变,这里需要使用commit:

methods: {
  add() {
    this.$store.commit('add');
  },
  reduce() {
    this.$store.commit('reduce');
  }
}
复制代码

2.5 action

Action 类似于 mutation,不同在于:

  1. Action 提交的是 mutation,而不是直接变更状态。
  2. Action 可以包含任意异步操作。前面说过mutation只能包含同步事务,所以在处理异步事务就需要Action,通过Action控制了异步这一过程,之后再去调用mutation里面的方法来改变状态。

这里我直接贴代码来一目了然,首先我定义了一个状态product:

state: {
  product: 'car'
}
复制代码

然后再mutation中定义一个方法:

changeProduct(state, payload) {
  state.product = payload.change;
}
复制代码

在action中定义:

actions: {
  changeProduct(context, payload) { // 这个context是一个与 store 实例具有相同方法和属性的对象
    // 调用mutation里的changeProduct方法
    // context.commit('changeProduct', {change: 'ship'});
    // 改成异步方式
    // setTimeout(() => {
    //   context.commit('changeProduct', {change: 'ship'});
    // }, 1500)
    // 使用载荷
    let temp = 'ship+' + payload.extraInfo; 
    setTimeout(() => {
      context.commit('changeProduct', {change: temp});
    }, 1500)
  }
}
复制代码

在组件methods中定义事件触发分发:

methods: {
  selectProduct() {
    // this.$store.dispatch('changeProduct')
    // 载荷方式分发
    // this.$store.dispatch('changeProduct', {
    //   extraInfo: 'sportcar'
    // })
    // 或者这种
    this.$store.dispatch({
      type: 'changeProduct',
      extraInfo: '->sportcar'
    })
  }
},
复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享