Vuex从入门到精通

简介: vuex是什么?官方给出的解释是:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 + 库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。看完官方解释后,你可能对状态管理模式很疑惑,对于状态管理模式,官方给出了详细的解释。这个状态自管理应用包含以下几个部分:状态,驱动应用的数据源;视图,以声明方式将状态映射到视图;操作,响应在视图上的用户输入导致的状态变化。

文章目录


前言

概念


vuex是什么?

官方给出的解释是:


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


看完官方解释后,你可能对状态管理模式很疑惑,对于状态管理模式,官方给出了详细的解释。

这个状态自管理应用包含以下几个部分:

  • 状态,驱动应用的数据源;
  • 视图,以声明方式将状态映射到视图;
  • 操作,响应在视图上的用户输入导致的状态变化。
  • 详细的视图演示
  • 如何理解这个图示呢?我们先从字面意思上理解,Actions的汉语意思是动作,行为Mutations意思是加工,修改。下面我将通过一个加减数的案例来解释这个图示

**

绿色框**内Vue Components视为一个vue实例化对象,我们把它看作数字count

流程图第一个Dispatch其实是一个函数,直接调用就行,假如我们要定义一个加的方法,应该这样去写dispatch(‘jia’,1),第一个参数填你定义的名称,第二个填你要加的数字。

Actions内是一个object类型对象,在里面定义函数,{jia:function…}

Commit意为提交,它也是一个函数,直接调用,commit(‘jia’,1)

Mutations也是一个object类型对象,里面是一个函数类型jia:function function会拿到两个东西,一个是state,另一个是加的参数:1,所以在函数内我们只用写:state.sum+=2。然后底层自动走mutate,这个不是一个api

State也是一个object类型对象形式,到达这一步时,假如原本sum为0,当1传过来时,sum自动变成1,通过render渲染到页面

我们发现,Actions里的过程和Mutations里的差不多,所以,我们也可以直接跳过Actions这一步,具体应用场景在下面几节会讲到



通俗点讲,vuex就是在Vue中实现集中式状态(数据)管理的一个Vue插件,对vue应用中多个组件的共享状态进行集中式的管理(读/写),也是一种组件间通信的方式,且适用于任意组件间通信。


使用场景

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


如果您不打算开发大型单页应用,使用 Vuex 可能是繁琐冗余的。确实是如此——如果您的应用够简单,您最好不要使用 Vuex。一个简单的

store 模式就足够您所需了。但是,如果您需要构建一个中大型单页应用,您很可能会考虑如何更好地在组件外部管理状态,Vuex

将会成为自然而然的选择。


搭建vue环境


创建文件

src/store/index.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
})

传入配置项

在main.js中创建vm时传入store配置项

......
//引入store
import store from './store'
......
//创建vm
new Vue({
  el:'#app',
  render: h => h(App),
  store
})

基本使用


初始化数据

1.初始化数据、配置actions、配置mutations,操作文件index.js

//引入Vue核心库
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
//引用Vuex
Vue.use(Vuex)
const actions = {
    //响应组件中加的动作
  jia(context,value){
    // console.log('actions中的jia被调用了',miniStore,value)
    context.commit('JIA',value)
  },
}
const mutations = {
    //执行加
  JIA(state,value){
    // console.log('mutations中的JIA被调用了',state,value)
    state.sum += value
  }
}
//初始化数据
const state = {
   sum:0
}
//创建并暴露store
export default new Vuex.Store({
  actions,
  mutations,
  state,
})

2.组件中读取vuex中的数据:$store.state.sum

3.组件中修改vuex中的数据:$store.dispatch('action中的方法名',数据) 或 $store.commit('mutations中的方法名',数据)

备注:若没有网络请求或其他业务逻辑,组件中也可以越过actions,即不写dispatch,直接编写commit


getters的使用

1.概念:当state中的数据需要经过加工后再使用时,可以使用getters加工。

2.在index.js中追加getters配置

......
const getters = {
  bigSum(state){
    return state.sum * 10
  }
}
//创建并暴露store
export default new Vuex.Store({
  ......
  getters
})

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


map方法使用

1.mapState方法:用于帮助我们映射state中的数据为计算属性

computed: {
    //借助mapState生成计算属性:sum、school、subject(对象写法)
     ...mapState({sum:'sum',school:'school',subject:'subject'}),
    //借助mapState生成计算属性:sum、school、subject(数组写法)
    ...mapState(['sum','school','subject']),
},

2.mapGetters方法:用于帮助我们映射getters中的数据为计算属性

computed: {
    //借助mapGetters生成计算属性:bigSum(对象写法)
    ...mapGetters({bigSum:'bigSum'}),
    //借助mapGetters生成计算属性:bigSum(数组写法)
    ...mapGetters(['bigSum'])
},

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

methods:{
    //靠mapActions生成:incrementOdd、incrementWait(对象形式)
    ...mapActions({incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
    //靠mapActions生成:incrementOdd、incrementWait(数组形式)
    ...mapActions(['jiaOdd','jiaWait'])
}

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

methods:{
    //靠mapActions生成:increment、decrement(对象形式)
    ...mapMutations({increment:'JIA',decrement:'JIAN'}),
    //靠mapMutations生成:JIA、JIAN(对象形式)
    ...mapMutations(['JIA','JIAN']),
}

备注:mapActions与mapMutations使用时,若需要传递参数需要:在模板中绑定事件时传递好参数,否则参数是事件对象。


模块化,命名空间


目的

让代码更好维护,让多种数据分类更加明确。


开启命名空间

修改index.js代码

const countAbout = {
  namespaced:true,//开启命名空间
  state:{x:1},
  mutations: { ... },
  actions: { ... },
  getters: {
    bigSum(state){
       return state.sum * 10
    }
  }
}
const personAbout = {
  namespaced:true,//开启命名空间
  state:{ ... },
  mutations: { ... },
  actions: { ... }
}
const store = new Vuex.Store({
  modules: {
    countAbout,
    personAbout
  }
})

组件中读取state数据

//方式一:自己直接读取
this.$store.state.personAbout.list
//方式二:借助mapState读取:
...mapState('countAbout',['sum','school','subject']),

组件中读取getters数据

//方式一:自己直接读取
this.$store.getters['personAbout/firstPersonName']
//方式二:借助mapGetters读取:
...mapGetters('countAbout',['bigSum'])

开启命名空间后,组件中调用dispatch

//方式一:自己直接dispatch
this.$store.dispatch('personAbout/addPersonWang',person)
//方式二:借助mapActions:
...mapActions('countAbout',{incrementOdd:'jiaOdd',incrementWait:'jiaWait'})

开启命名空间后,组件中调用commit

//方式一:自己直接commit
this.$store.commit('personAbout/ADD_PERSON',person)
//方式二:借助mapMutations:
...mapMutations('countAbout',{increment:'JIA',decrement:'JIAN'}),

实例应用

求和案例(纯vuex)

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="increment">+</button>
    <button @click="decrement">-</button>
    <button @click="incrementOdd">当前求和为奇数再加</button>
    <button @click="incrementWait">等一等再加</button>
  </div>
</template>
<script>
  export default {
    name:'Count',
    data() {
      return {
        n:1, //用户选择的数字
      }
    },
    methods: {
      increment(){
        this.$store.commit('JIA',this.n)
      },
      decrement(){
        this.$store.commit('JIAN',this.n)
      },
      incrementOdd(){
        this.$store.dispatch('jiaOdd',this.n)
      },
      incrementWait(){
        this.$store.dispatch('jiaWait',this.n)
      },
    },
    mounted() {
      console.log('Count',this)
    },
  }
</script>
<style lang="css">
  button{
    margin-left: 5px;
  }
</style>

index.js

//该文件用于创建Vuex中最为核心的store
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
//应用Vuex插件
Vue.use(Vuex)
//准备actions——用于响应组件中的动作
const actions = {
  /* jia(context,value){
    console.log('actions中的jia被调用了')
    context.commit('JIA',value)
  },
  jian(context,value){
    console.log('actions中的jian被调用了')
    context.commit('JIAN',value)
  }, */
  jiaOdd(context,value){
    console.log('actions中的jiaOdd被调用了')
    if(context.state.sum % 2){
      context.commit('JIA',value)
    }
  },
  jiaWait(context,value){
    console.log('actions中的jiaWait被调用了')
    setTimeout(()=>{
      context.commit('JIA',value)
    },500)
  }
}
//准备mutations——用于操作数据(state)
const mutations = {
  JIA(state,value){
    console.log('mutations中的JIA被调用了')
    state.sum += value
  },
  JIAN(state,value){
    console.log('mutations中的JIAN被调用了')
    state.sum -= value
  }
}
//准备state——用于存储数据
const state = {
  sum:0 //当前的和
}
//创建并暴露store
export default new Vuex.Store({
  actions,
  mutations,
  state,
})

求和案例(getters)

Count.vue

<template>
  <div>
    <h1>当前求和为:{{$store.state.sum}}</h1>
    <h3>当前求和放大10倍为:{{$store.getters.bigSum}}</h3>
    <select v-model.number="n">
      <option value="1">1</option>
      <option value="2">2</option>
      <option value="3">3</option>
    </select>
    <button @click="increment">+</button>
    <button @click="decrement">-</button>
    <button @click="incrementOdd">当前求和为奇数再加</button>
    <button @click="incrementWait">等一等再加</button>
  </div>
</template>
<script>
  export default {
    name:'Count',
    data() {
      return {
        n:1, //用户选择的数字
      }
    },
    methods: {
      increment(){
        this.$store.commit('JIA',this.n)
      },
      decrement(){
        this.$store.commit('JIAN',this.n)
      },
      incrementOdd(){
        this.$store.dispatch('jiaOdd',this.n)
      },
      incrementWait(){
        this.$store.dispatch('jiaWait',this.n)
      },
    },
    mounted() {
      console.log('Count',this.$store)
    },
  }
</script>
<style lang="css">
  button{
    margin-left: 5px;
  }
</style>

index.js

//该文件用于创建Vuex中最为核心的store
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
//应用Vuex插件
Vue.use(Vuex)
//准备actions——用于响应组件中的动作
const actions = {
  /* jia(context,value){
    console.log('actions中的jia被调用了')
    context.commit('JIA',value)
  },
  jian(context,value){
    console.log('actions中的jian被调用了')
    context.commit('JIAN',value)
  }, */
  jiaOdd(context,value){
    console.log('actions中的jiaOdd被调用了')
    if(context.state.sum % 2){
      context.commit('JIA',value)
    }
  },
  jiaWait(context,value){
    console.log('actions中的jiaWait被调用了')
    setTimeout(()=>{
      context.commit('JIA',value)
    },500)
  }
}
//准备mutations——用于操作数据(state)
const mutations = {
  JIA(state,value){
    console.log('mutations中的JIA被调用了')
    state.sum += value
  },
  JIAN(state,value){
    console.log('mutations中的JIAN被调用了')
    state.sum -= value
  }
}
//准备state——用于存储数据
const state = {
  sum:0 //当前的和
}
//准备getters——用于将state中的数据进行加工
const getters = {
  bigSum(state){
    return state.sum*10
  }
}
//创建并暴露store
export default new Vuex.Store({
  actions,
  mutations,
  state,
  getters
})

求和(mapState,mapGetters)

Count.vue

<template>
  <div>
    <h1>当前求和为:{{sum}}</h1>
    <h3>当前求和放大10倍为:{{bigSum}}</h3>
    <h3>我在{{school}},学习{{subject}}</h3>
    <select v-model.number="n">
      <option value="1">1</option>
      <option value="2">2</option>
      <option value="3">3</option>
    </select>
    <button @click="increment">+</button>
    <button @click="decrement">-</button>
    <button @click="incrementOdd">当前求和为奇数再加</button>
    <button @click="incrementWait">等一等再加</button>
  </div>
</template>
<script>
  import {mapState,mapGetters} from 'vuex'
  export default {
    name:'Count',
    data() {
      return {
        n:1, //用户选择的数字
      }
    },
    computed:{
      //靠程序员自己亲自去写计算属性
      /* sum(){
        return this.$store.state.sum
      },
      school(){
        return this.$store.state.school
      },
      subject(){
        return this.$store.state.subject
      }, */
      //借助mapState生成计算属性,从state中读取数据。(对象写法)
      // ...mapState({he:'sum',xuexiao:'school',xueke:'subject'}),
      //借助mapState生成计算属性,从state中读取数据。(数组写法)
      ...mapState(['sum','school','subject']),
      /* ******************************************************************** */
      /* bigSum(){
        return this.$store.getters.bigSum
      }, */
      //借助mapGetters生成计算属性,从getters中读取数据。(对象写法)
      // ...mapGetters({bigSum:'bigSum'})
      //借助mapGetters生成计算属性,从getters中读取数据。(数组写法)
      ...mapGetters(['bigSum'])
    },
    methods: {
      increment(){
        this.$store.commit('JIA',this.n)
      },
      decrement(){
        this.$store.commit('JIAN',this.n)
      },
      incrementOdd(){
        this.$store.dispatch('jiaOdd',this.n)
      },
      incrementWait(){
        this.$store.dispatch('jiaWait',this.n)
      },
    },
    mounted() {
      const x = mapState({he:'sum',xuexiao:'school',xueke:'subject'})
      console.log(x)
    },
  }
</script>
<style lang="css">
  button{
    margin-left: 5px;
  }
</style>

index.js

//该文件用于创建Vuex中最为核心的store
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
//应用Vuex插件
Vue.use(Vuex)
//准备actions——用于响应组件中的动作
const actions = {
  /* jia(context,value){
    console.log('actions中的jia被调用了')
    context.commit('JIA',value)
  },
  jian(context,value){
    console.log('actions中的jian被调用了')
    context.commit('JIAN',value)
  }, */
  jiaOdd(context,value){
    console.log('actions中的jiaOdd被调用了')
    if(context.state.sum % 2){
      context.commit('JIA',value)
    }
  },
  jiaWait(context,value){
    console.log('actions中的jiaWait被调用了')
    setTimeout(()=>{
      context.commit('JIA',value)
    },500)
  }
}
//准备mutations——用于操作数据(state)
const mutations = {
  JIA(state,value){
    console.log('mutations中的JIA被调用了')
    state.sum += value
  },
  JIAN(state,value){
    console.log('mutations中的JIAN被调用了')
    state.sum -= value
  }
}
//准备state——用于存储数据
const state = {
  sum:0, //当前的和
  school:'学校',
  subject:'前端'
}
//准备getters——用于将state中的数据进行加工
const getters = {
  bigSum(state){
    return state.sum*10
  }
}
//创建并暴露store
export default new Vuex.Store({
  actions,
  mutations,
  state,
  getters
})

求和(mapActions,mapMutations)

Count.vue

<template>
  <div>
    <h1>当前求和为:{{sum}}</h1>
    <h3>当前求和放大10倍为:{{bigSum}}</h3>
    <h3>我在{{school}},学习{{subject}}</h3>
    <select v-model.number="n">
      <option value="1">1</option>
      <option value="2">2</option>
      <option value="3">3</option>
    </select>
    <button @click="increment(n)">+</button>
    <button @click="decrement(n)">-</button>
    <button @click="incrementOdd(n)">当前求和为奇数再加</button>
    <button @click="incrementWait(n)">等一等再加</button>
  </div>
</template>
<script>
  import {mapState,mapGetters,mapMutations,mapActions} from 'vuex'
  export default {
    name:'Count',
    data() {
      return {
        n:1, //用户选择的数字
      }
    },
    computed:{
      //借助mapState生成计算属性,从state中读取数据。(对象写法)
      // ...mapState({he:'sum',xuexiao:'school',xueke:'subject'}),
      //借助mapState生成计算属性,从state中读取数据。(数组写法)
      ...mapState(['sum','school','subject']),
      /* ******************************************************************** */
      //借助mapGetters生成计算属性,从getters中读取数据。(对象写法)
      // ...mapGetters({bigSum:'bigSum'})
      //借助mapGetters生成计算属性,从getters中读取数据。(数组写法)
      ...mapGetters(['bigSum'])
    },
    methods: {
      //程序员亲自写方法
      /* increment(){
        this.$store.commit('JIA',this.n)
      },
      decrement(){
        this.$store.commit('JIAN',this.n)
      }, */
      //借助mapMutations生成对应的方法,方法中会调用commit去联系mutations(对象写法)
      ...mapMutations({increment:'JIA',decrement:'JIAN'}),
      //借助mapMutations生成对应的方法,方法中会调用commit去联系mutations(数组写法)
      // ...mapMutations(['JIA','JIAN']),
      /* ************************************************* */
      //程序员亲自写方法
      /* incrementOdd(){
        this.$store.dispatch('jiaOdd',this.n)
      },
      incrementWait(){
        this.$store.dispatch('jiaWait',this.n)
      }, */
      //借助mapActions生成对应的方法,方法中会调用dispatch去联系actions(对象写法)
      ...mapActions({incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
      //借助mapActions生成对应的方法,方法中会调用dispatch去联系actions(数组写法)
      // ...mapActions(['jiaOdd','jiaWait'])
    },
    mounted() {
      const x = mapState({he:'sum',xuexiao:'school',xueke:'subject'})
      console.log(x)
    },
  }
</script>
<style lang="css">
  button{
    margin-left: 5px;
  }
</style>

index.js

//该文件用于创建Vuex中最为核心的store
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
//应用Vuex插件
Vue.use(Vuex)
//准备actions——用于响应组件中的动作
const actions = {
  /* jia(context,value){
    console.log('actions中的jia被调用了')
    context.commit('JIA',value)
  },
  jian(context,value){
    console.log('actions中的jian被调用了')
    context.commit('JIAN',value)
  }, */
  jiaOdd(context,value){
    console.log('actions中的jiaOdd被调用了')
    if(context.state.sum % 2){
      context.commit('JIA',value)
    }
  },
  jiaWait(context,value){
    console.log('actions中的jiaWait被调用了')
    setTimeout(()=>{
      context.commit('JIA',value)
    },500)
  }
}
//准备mutations——用于操作数据(state)
const mutations = {
  JIA(state,value){
    console.log('mutations中的JIA被调用了')
    state.sum += value
  },
  JIAN(state,value){
    console.log('mutations中的JIAN被调用了')
    state.sum -= value
  }
}
//准备state——用于存储数据
const state = {
  sum:0, //当前的和
  school:'学校',
  subject:'前端'
}
//准备getters——用于将state中的数据进行加工
const getters = {
  bigSum(state){
    return state.sum*10
  }
}
//创建并暴露store
export default new Vuex.Store({
  actions,
  mutations,
  state,
  getters
})

多组件共享数据

Count.vue

<template>
  <div>
    <h1>当前求和为:{{sum}}</h1>
    <h3>当前求和放大10倍为:{{bigSum}}</h3>
    <h3>我在{{school}},学习{{subject}}</h3>
    <h3 style="color:red">Person组件的总人数是:{{personList.length}}</h3>
    <select v-model.number="n">
      <option value="1">1</option>
      <option value="2">2</option>
      <option value="3">3</option>
    </select>
    <button @click="increment(n)">+</button>
    <button @click="decrement(n)">-</button>
    <button @click="incrementOdd(n)">当前求和为奇数再加</button>
    <button @click="incrementWait(n)">等一等再加</button>
  </div>
</template>
<script>
  import {mapState,mapGetters,mapMutations,mapActions} from 'vuex'
  export default {
    name:'Count',
    data() {
      return {
        n:1, //用户选择的数字
      }
    },
    computed:{
      //借助mapState生成计算属性,从state中读取数据。(数组写法)
      ...mapState(['sum','school','subject','personList']),
      //借助mapGetters生成计算属性,从getters中读取数据。(数组写法)
      ...mapGetters(['bigSum'])
    },
    methods: {
      //借助mapMutations生成对应的方法,方法中会调用commit去联系mutations(对象写法)
      ...mapMutations({increment:'JIA',decrement:'JIAN'}),
      //借助mapActions生成对应的方法,方法中会调用dispatch去联系actions(对象写法)
      ...mapActions({incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
    },
    mounted() {
      // const x = mapState({he:'sum',xuexiao:'school',xueke:'subject'})
      // console.log(x)
    },
  }
</script>
<style lang="css">
  button{
    margin-left: 5px;
  }
</style>

person.vue

<template>
  <div>
    <h1>人员列表</h1>
    <h3 style="color:red">Count组件求和为:{{sum}}</h3>
    <input type="text" placeholder="请输入名字" v-model="name">
    <button @click="add">添加</button>
    <ul>
      <li v-for="p in personList" :key="p.id">{{p.name}}</li>
    </ul>
  </div>
</template>
<script>
  import {nanoid} from 'nanoid'
  export default {
    name:'Person',
    data() {
      return {
        name:''
      }
    },
    computed:{
      personList(){
        return this.$store.state.personList
      },
      sum(){
        return this.$store.state.sum
      }
    },
    methods: {
      add(){
        const personObj = {id:nanoid(),name:this.name}
        this.$store.commit('ADD_PERSON',personObj)
        this.name = ''
      }
    },
  }
</script>

index.js

//该文件用于创建Vuex中最为核心的store
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
//应用Vuex插件
Vue.use(Vuex)
//准备actions——用于响应组件中的动作
const actions = {
  /* jia(context,value){
    console.log('actions中的jia被调用了')
    context.commit('JIA',value)
  },
  jian(context,value){
    console.log('actions中的jian被调用了')
    context.commit('JIAN',value)
  }, */
  jiaOdd(context,value){
    console.log('actions中的jiaOdd被调用了')
    if(context.state.sum % 2){
      context.commit('JIA',value)
    }
  },
  jiaWait(context,value){
    console.log('actions中的jiaWait被调用了')
    setTimeout(()=>{
      context.commit('JIA',value)
    },500)
  }
}
//准备mutations——用于操作数据(state)
const mutations = {
  JIA(state,value){
    console.log('mutations中的JIA被调用了')
    state.sum += value
  },
  JIAN(state,value){
    console.log('mutations中的JIAN被调用了')
    state.sum -= value
  },
  ADD_PERSON(state,value){
    console.log('mutations中的ADD_PERSON被调用了')
    state.personList.unshift(value)
  }
}
//准备state——用于存储数据
const state = {
  sum:0, //当前的和
  school:'学校',
  subject:'前端',
  personList:[
    {id:'001',name:'张三'}
  ]
}
//准备getters——用于将state中的数据进行加工
const getters = {
  bigSum(state){
    return state.sum*10
  }
}
//创建并暴露store
export default new Vuex.Store({
  actions,
  mutations,
  state,
  getters
})

模块化编码


count.js

//求和相关的配置
export default {
  namespaced:true,
  actions:{
    jiaOdd(context,value){
      console.log('actions中的jiaOdd被调用了')
      if(context.state.sum % 2){
        context.commit('JIA',value)
      }
    },
    jiaWait(context,value){
      console.log('actions中的jiaWait被调用了')
      setTimeout(()=>{
        context.commit('JIA',value)
      },500)
    }
  },
  mutations:{
    JIA(state,value){
      console.log('mutations中的JIA被调用了')
      state.sum += value
    },
    JIAN(state,value){
      console.log('mutations中的JIAN被调用了')
      state.sum -= value
    },
  },
  state:{
    sum:0, //当前的和
    school:'学校',
    subject:'前端',
  },
  getters:{
    bigSum(state){
      return state.sum*10
    }
  },
}

person.js

//人员管理相关的配置
import axios from 'axios'
import { nanoid } from 'nanoid'
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=social').then(
        response => {
          context.commit('ADD_PERSON',{id:nanoid(),name:response.data})
        },
        error => {
          alert(error.message)
        }
      )
    }
  },
  mutations:{
    ADD_PERSON(state,value){
      console.log('mutations中的ADD_PERSON被调用了')
      state.personList.unshift(value)
    }
  },
  state:{
    personList:[
      {id:'001',name:'张三'}
    ]
  },
  getters:{
    firstPersonName(state){
      return state.personList[0].name
    }
  },
}

index.js

//该文件用于创建Vuex中最为核心的store
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
import countOptions from './count'
import personOptions from './person'
//应用Vuex插件
Vue.use(Vuex)
//创建并暴露store
export default new Vuex.Store({
  modules:{
    countAbout:countOptions,
    personAbout:personOptions
  }
})

Count.vue

<template>
  <div>
    <h1>当前求和为:{{sum}}</h1>
    <h3>当前求和放大10倍为:{{bigSum}}</h3>
    <h3>我在{{school}},学习{{subject}}</h3>
    <h3 style="color:red">Person组件的总人数是:{{personList.length}}</h3>
    <select v-model.number="n">
      <option value="1">1</option>
      <option value="2">2</option>
      <option value="3">3</option>
    </select>
    <button @click="increment(n)">+</button>
    <button @click="decrement(n)">-</button>
    <button @click="incrementOdd(n)">当前求和为奇数再加</button>
    <button @click="incrementWait(n)">等一等再加</button>
  </div>
</template>
<script>
  import {mapState,mapGetters,mapMutations,mapActions} from 'vuex'
  export default {
    name:'Count',
    data() {
      return {
        n:1, //用户选择的数字
      }
    },
    computed:{
      //借助mapState生成计算属性,从state中读取数据。(数组写法)
      ...mapState('countAbout',['sum','school','subject']),
      ...mapState('personAbout',['personList']),
      //借助mapGetters生成计算属性,从getters中读取数据。(数组写法)
      ...mapGetters('countAbout',['bigSum'])
    },
    methods: {
      //借助mapMutations生成对应的方法,方法中会调用commit去联系mutations(对象写法)
      ...mapMutations('countAbout',{increment:'JIA',decrement:'JIAN'}),
      //借助mapActions生成对应的方法,方法中会调用dispatch去联系actions(对象写法)
      ...mapActions('countAbout',{incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
    },
    mounted() {
      console.log(this.$store)
    },
  }
</script>
<style lang="css">
  button{
    margin-left: 5px;
  }
</style>
<template>
  <div>
    <h1>人员列表</h1>
    <h3 style="color:red">Count组件求和为:{{sum}}</h3>
    <h3>列表中第一个人的名字是:{{firstPersonName}}</h3>
    <input type="text" placeholder="请输入名字" v-model="name">
    <button @click="add">添加</button>
    <button @click="addWang">添加一个姓王的人</button>
    <button @click="addPersonServer">添加一个人,名字随机</button>
    <ul>
      <li v-for="p in personList" :key="p.id">{{p.name}}</li>
    </ul>
  </div>
</template>
<script>
  import {nanoid} from 'nanoid'
  export default {
    name:'Person',
    data() {
      return {
        name:''
      }
    },
    computed:{
      personList(){
        return this.$store.state.personAbout.personList
      },
      sum(){
        return this.$store.state.countAbout.sum
      },
      firstPersonName(){
        return this.$store.getters['personAbout/firstPersonName']
      }
    },
    methods: {
      add(){
        const personObj = {id:nanoid(),name:this.name}
        this.$store.commit('personAbout/ADD_PERSON',personObj)
        this.name = ''
      },
      addWang(){
        const personObj = {id:nanoid(),name:this.name}
        this.$store.dispatch('personAbout/addPersonWang',personObj)
        this.name = ''
      },
      addPersonServer(){
        this.$store.dispatch('personAbout/addPersonServer')
      }
    },
  }
</script>

项目结构

Vuex 并不限制你的代码结构。但是,它规定了一些需要遵守的规则:


应用层级的状态应该集中到单个 store 对象中。

提交 mutation 是更改状态的唯一方法,并且这个过程是同步的。

异步逻辑都应该封装到 action 里面。

只要你遵守以上规则,如何组织代码随你便。如果你的 store 文件太大,只需将 action、mutation 和 getter 分割到单独的文件。


对于大型应用,我们会希望把 Vuex 相关代码分割到模块中。下面是项目结构示例:

├── index.html
├── main.js
├── api
│   └── ... # 抽取出API请求
├── components
│   ├── App.vue
│   └── ...
└── store
    ├── index.js          # 我们组装模块并导出 store 的地方
    ├── actions.js        # 根级别的 action
    ├── mutations.js      # 根级别的 mutation
    └── modules
        ├── cart.js       # 购物车模块
        └── products.js   # 产品模块



目录
相关文章
|
4月前
|
JavaScript 前端开发 开发者
Vue3 系列教程 — 为什么选择 Vue 框架? (开篇)
Vue3 系列教程 — 为什么选择 Vue 框架? (开篇)
|
7月前
Vuex相关面试题
Vuex相关面试题
79 2
|
存储 JavaScript 前端开发
vuex入门
vuex入门
63 0
|
7月前
|
存储 前端开发 JavaScript
【前端学习】—Vuex(十八)
【前端学习】—Vuex(十八)
|
移动开发 JavaScript 前端开发
【Vue2从入门到精通】零基础学习vue到底该如何上手
本文是为vue初学者整理的零基础快速上手vue的学习指南,希望能帮助到迷茫的你。
184 0
【Vue2从入门到精通】零基础学习vue到底该如何上手
|
JavaScript 前端开发
【Vue2从入门到精通】认识Vue组件化,这篇文章就够了
当我们在构建Vue应用程序时,组件化是一个非常重要的概念。Vue组件化将应用程序划分为更小、更可重用的部分,从而使应用程序更易于维护、测试和扩展。
227 0
|
开发工具 git
学习Pinia 第一章(介绍Pinia)
代码扁平化没有模块嵌套,只有 store 的概念,store 之间可以自由使用,每一个store都是独立的
102 0
学习Pinia 第一章(介绍Pinia)
|
JavaScript 前端开发 API
|
存储 JavaScript 开发工具