21. Vuex

21.1 搭建Vuex环境

  1. 下载安装Vuex npm i vuex
  2. 创建src/store/index.js该文件用于创建Vuex中最为核心的store.js文件

    //引入Vue
    import Vue from 'vue'
    //引入Vuex
    import Vuex from 'vuex'
    //应用Vuex
    Vue.use(Vuex)
    //准备actions对象--响应组件中用户的动作
    const  actions={
    }
    //准备mutations对象--修改state中的数据
    const mutations={
    }
    //准备state对象--报错具体的数据
    const state={
    }
    //创建并暴露store
    export default new Vuex.Store({
        actions,
        mutations,
        state
    })
  3. src/main.js中创建vm时传入store配置项

    //引入Vue
    import Vue from 'vue'
    //引入插件
    import vueResource from 'vue-resource'
    import store from './store'
    //使用插件
    Vue.use(vueResource)
    //引入App组件
    import App from './App'
    //关闭Vue的生产提示
    Vue.config.productionTip = false
    
    new Vue({
        el: "#app",
        store,
        render: h => h(App),
        beforeCreate() {
            Vue.prototype.$bus = this
        }
    })
    

21.2 基本使用

src/store/index.js

//引入Vue
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
//应用Vuex
Vue.use(Vuex)
//准备actions对象--响应组件中用户的动作
const  actions={
    add(context,value){
        context.commit("ADD",value)
    },
    reduce(context,value){
        context.commit("REDUCE",value)
    },
    addOdd(context,value){
        if(context.state.sum%2){
            context.commit("ADD",value)
        }
    },
    addWait(context,value){
        setTimeout(()=>{
            context.commit("ADD",value)
        },500)
    }
}
//准备mutations对象--修改state中的数据
const mutations={
    ADD(state,value){
        state.sum+=value
    },
    REDUCE(state,value){
        state.sum-=value
    }
}
//准备state对象--报错具体的数据
const state={
    sum:0
}
//创建并暴露store
export default new Vuex.Store({
    actions,
    mutations,
    state
})

src/components/Count.vue

<template>
  <div>
    <h1>当前求和的值为: {{ $store.state.sum }}</h1>
    <select v-model.number="n">
      <option value="1">1</option>
      <option value="2">2</option>
      <option value="3">3</option>
    </select>
    <button @click="add">+</button>
    <button @click="reduce">-</button>
    <button @click="addOdd">求和为奇数时再加</button>
    <button @click="addWait">等一等再加</button>
  </div>
</template>
<script>
export default {
  name: "Count",
  data() {
    return {
      n: 1,
    }
  },
  mounted() {
  }, methods: {
    //加法
    add() {
      this.$store.commit('ADD',this.n)
    },
    //减法
    reduce() {
      this.$store.commit('REDUCE',this.n)
    },
    //奇数时加
    addOdd() {
        this.$store.dispatch('addOdd',this.n)
    },
    //等等再加
    addWait() {
        this.$store.dispatch('addWait',this.n)
    },
  }
}
</script>
<style scoped>
button {
  margin-left: 5px;
}
</style>

21.3 getters的使用

  1. 概念: 当state中的数据需要经过加工后再使用时,可以使用getters加工
  2. src/store/index.js中追加getters配置

    //准备getters对象,用于将state中的数据进行加工
    const getters = {
        bigSum(state) {
            return state.sum * 10
        }
    }
    //创建并暴露store
    export default new Vuex.Store({
        ......
        getters
    })

    组件中读取数据: $store.getters.bigSum

21.4 mapState和mapGetters

mapState用于帮助我们映射state中的数据为计算属性

mapGetters用于帮助我们映射getters中的数据为计算属性

src/components/Count.vue

<template>
  <div>
    <h1>当前求和的值为: {{ sum }}</h1>
    <h3>当前求和的10倍为: {{ bigSum }}</h3>
    <h2>我在{{ school }},学习{{ subject }}</h2>
    <select v-model.number="n">
      <option value="1">1</option>
      <option value="2">2</option>
      <option value="3">3</option>
    </select>
    <button @click="add">+</button>
    <button @click="reduce">-</button>
    <button @click="addOdd">求和为奇数时再加</button>
    <button @click="addWait">等一等再加</button>
  </div>
</template>
<script>
import {mapState,mapGetters} from 'vuex'

export default {
  name: "Count",
  data() {
    return {
      n: 1,
    }
  },
  computed:{
    // he(){
    //   return this.$store.state.sum
    // },
    //借助mapState生成计算属性(对象写法)
    // ...mapState({sum:"sum",school:"school",subject:"subject"}),
    //借助mapState生成计算属性(数组写法)
    ...mapState(['sum','school','subject']),

    //借助mapGetters生成计算属性(对象写法)
    // ...mapGetters({bigSum:"bigSum"})

    //借助mapGetters生成计算属性(数组写法)
    ...mapGetters(["bigSum"])
  },
  mounted() {
    console.log("Count", this.$store)
  },
  methods: {
    //加法
    add() {
      this.$store.commit('ADD', this.n)
    },
    //减法
    reduce() {
      this.$store.commit('REDUCE', this.n)
    },
    //奇数时加
    addOdd() {
      this.$store.dispatch('addOdd', this.n)
    },
    //等等再加
    addWait() {
      this.$store.dispatch('addWait', this.n)
    },
  }
}
</script>
<style scoped>
button {
  margin-left: 5px;
}
</style>

21.5 mapMutations和mapActions

mapMutations方法用于帮助我们生成与mutations对话的方法,即: 包含$store.commit(xxx)的函数

mapActions方法用于帮助我们生成与actions对话的方法,即: 包含$store.dispatch(xxx)的函数

src/components/Count.vue

<template>
  <div>
    <h1>当前求和的值为: {{ sum }}</h1>
    <h3>当前求和的10倍为: {{ bigSum }}</h3>
    <h2>我在{{ school }},学习{{ subject }}</h2>
    <select v-model.number="n">
      <option value="1">1</option>
      <option value="2">2</option>
      <option value="3">3</option>
    </select>
    <button @click="ADD(n)">+</button>
    <button @click="REDUCE(n)">-</button>
    <button @click="addOdd(n)">求和为奇数时再加</button>
    <button @click="addWait(n)">等一等再加</button>
  </div>
</template>
<script>
import {mapState,mapGetters,mapActions,mapMutations} from 'vuex'

export default {
  name: "Count",
  data() {
    return {
      n: 1,
    }
  },
  computed:{
    // he(){
    //   return this.$store.state.sum
    // },
    //借助mapState生成计算属性(对象写法)
    // ...mapState({sum:"sum",school:"school",subject:"subject"}),
    //借助mapState生成计算属性(数组写法)
    ...mapState(['sum','school','subject']),

    //借助mapGetters生成计算属性(对象写法)
    // ...mapGetters({bigSum:"bigSum"})

    //借助mapGetters生成计算属性(数组写法)
    ...mapGetters(["bigSum"])
  },
  mounted() {
    console.log("Count", this.$store)
  },
  methods: {
    // //加法
    // add() {
    //   this.$store.commit('ADD', this.n)
    // },
    // //减法
    // reduce() {
    //   this.$store.commit('REDUCE', this.n)
    // },
    //借助mapMutations生成调用commit的方法(对象写法)
    // ...mapMutations({add:"ADD",reduce:"REDUCE"}),
    //借助mapMutations生成调用commit的方法(数组写法)
    ...mapMutations(["ADD","REDUCE"]),



    //******************************************************//
    //奇数时加
    // addOdd() {
    //   this.$store.dispatch('addOdd', this.n)
    // },
    // //等等再加
    // addWait() {
    //   this.$store.dispatch('addWait', this.n)
    // },
    //借助mapActions生成调用dispatch的方法(对象写法)
    // ...mapActions({addOdd:"addOdd",addWait:"addWait"})
    //借助mapActions生成调用dispatch的方法(数组写法)
    ...mapActions(['addOdd','addWait'])
  }
}
</script>
<style scoped>
button {
  margin-left: 5px;
}
</style>

21.6 模块化+命名空间

  1. 目的:让代码更好维护,让多种数据分类更加明确
  2. 修改store.js

    //引入Vue
    import Vue from 'vue'
    //引入Vuex
    import Vuex from 'vuex'
    //应用Vuex
    Vue.use(Vuex)
    import countAbout from './count'
    import personAbout from './person'
    
    
    //创建并暴露store
    export default new Vuex.Store({
        modules:{
            countAbout:countAbout,
            personAbout:personAbout
        }
    })

    count.js

    export default {
        //开启命名空间
        namespaced:true,
        actions:{
            add(context, value) {
                context.commit("ADD", value)
            },
            reduce(context, value) {
                context.commit("REDUCE", value)
            },
            addOdd(context, value) {
                if (context.state.sum % 2) {
                    context.commit("ADD", value)
                }
            },
            addWait(context, value) {
                setTimeout(() => {
                    context.commit("ADD", value)
                }, 500)
            }
        },
        mutations:{
            ADD(state, value) {
                state.sum += value
            },
            REDUCE(state, value) {
                state.sum -= value
            },
        },
        state:{
            sum: 0,
            school:"南方IT",
            subject:"软件工程",
        },
        getters:{
            bigSum(state) {
                return state.sum * 10
            }
        },
    
    }

    person.js

    import {nanoid} from "nanoid";
    import axios from "axios";
    export default {
        //开启命名空间
        namespaced:true,
        actions:{
            //添加一个姓王的人
            addPersonWang(context,value){
                if(value.name.indexOf("王")===0){
                    context.commit("ADD_PERSON",value)
                }else{
                    alert("添加人员的姓必须为王")
                }
            },
            addPersonServer(context){
                axios.get("https://api.uixsj.cn/hitokoto/get?type=zha").then(
                    response=>{
                        context.commit("ADD_PERSON",{id:nanoid(),name:response.data})
                    },
                    error=>{
                        alert(error.message)
                    }
                )
            }
        },
        mutations:{
            ADD_PERSON(state, value){
                state.personList.unshift(value)
            }
        },
        state:{
            personList:[
                {id:nanoid(),name:"张三"}
            ]
        },
        getters:{
            //获取人员列表里的第一个人的名称
            FirstPersonName(state){
                return state.personList[0].name
            }
        },
    
    }
  3. 开启命名空间后,组件中读取state数据

    //方式一: 自己直接读取
    this.$store.state.personAbout.personLit
    //方式二: 借助mapState读取
    ...mapState('countAbout',['sum','school','subject'])
  4. 开启命名空间后,组件中读取getters数据

    //方式一: 自己直接读取
    this.$store.getters["personAbout/FirstPersonName"]
    //方式二: 借助mapGetters读取
    ...mapGetters('countAbout',["bigSum"])
  5. 开启命名空间后,组件中调用dispatch

    //方式一: 自己直接dispatch
    this.$store.dispatch("personAbout/addPersonWang",personObj)
    //方式二: 借助mapActions:
    ...mapActions('countAbout',['addOdd','addWait'])
  6. 开启命名空间后,组件中调用commit

    //方式一: 自己直接commit
    his.$store.commit("personAbout/ADD_PERSON",personObj)
    //方式二: 借助mapMutations:
    ...mapMutations('countAbout',["ADD","REDUCE"])
最后修改:2023 年 01 月 31 日
如果觉得我的文章对你有用,请随意赞赏