Vuex粗解

Vuex定义

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式

说得直白点,vuex就是vue.js中管理数据状态的一个库,通过创建一个集中的数据存储,供程序中所有组件访问。

一个数据只要放在了vuex中,当前项目所有的组件都可以直接访问这个数据。

每一个 Vuex 应用的核心就是 store(仓库)。“store”基本上就是一个容器,它包含着你的应用中大部分的状态 (state)。Vuex 和单纯的全局对象有以下两点不同:

vuex有以下常用的几个核心属性概念:

  • State
  • Getters
  • Mutations
  • Actions
  • Modules

一.State 单一状态树

vuex中的state类似于data,用于存放数据,只不过这个数据是所有组件公用的。

定义

export default new Vuex.Store({
  state: {
    num: 0	// 定义了一个num
  }})

组件中调用:

<template>
    <h3>{{$store.state.num}}</h3>
</template>

简化调用:

<h3>{{num}}</h3>

但是调用state时需要在computed写下相关的定义

computed: {
  num(){
  	return this.$store.state.num
  }}

二,Getters 计算属性

vuex中的getters类似于computed计算属性,getters的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。

人话:保存数据,并且可以使用State中的数据进行运算

定义

export default new Vuex.Store({
  state: {num: 2},
  getters: {
    // 这里的参数state可以让我们快速获取到仓库中的数据
    doubleNum(state) { 
      return state.num * 2;
    }}
})

组件中调用:

<template>
    <h3>{{$store.getters.doubleNum}}</h3>
</template>
//同样也可以使用简化写法,类似于State

三,Mutations 同步修改数据方法

人话:用于保存同步修改数据的一些方法

export default new Vuex.Store({
  state: {
    num: 2
  },
  mutations: {
    // payload专业名称为“载荷”,其实就是个参数
    addNum(state, payload) {
      state.num += payload;
    }}
})

组件中

export default {
  methods: {
    btnClick(){
      // 使用commit来触发事件,第二个参数是要传递给payload的数据
      this.$store.commit('addNum', 2)
    }
  }};

四,Actions 异步修改数据方法

人话:保存异步修改数据的一些方法

export default new Vuex.Store({
  state: {
    num: 2
  },
  mutations: {
    addNum(state, payload) {
      state.num += payload;
    }},
  actions: {
    // context是一个对象,包含了commit和state
    AsyncAddNum(context,payload) { 
      setTimeout(() => {
        context.commit('addNum', payload)
      }, 1000)
    }}})

组件中:

<template>
 <div>
    <h3>{{$store.state.num}}</h3>
    <button @click="btnClick">累加2</button>
 </div>
</template>
 
<script>
export default {
  methods: {
    btnClick(){
      // dispatch是分发到意思,其实也是触发Actions中的方法
      this.$store.dispatch('AsyncAddNum', 2)
    }}};
</script>

五.辅助函数

获取单个数据或触发某个方法比较容易,我们直接拿到和触发就行,但如果要获取的数据和触发的方法很多很多个,我们获取与调用起来就比较麻烦了,这时候我们需要借用辅助函数。

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

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    num: 2,                              //基础数值
    title: '标题'
  },
  getters: {
    doubleNum(state) {                    //双倍数值
      return state.num * 1;
    }},
  mutations: {
    addNum(state, payload) {              //增加数值
      state.num += payload;
    },
    cutNum(state, payload) {               //减去数值
      state.num -= payload;
    }},
  actions: {
    AsyncAddNum({ commit },payload) {      //延迟增加数值
      setTimeout(() => {
        commit('addNum', payload)
      }, 300)},
    AsyncCutNum({ commit }, payload) {     //延迟减去数值
      setTimeout(() => {
        commit('cutNum', payload)
      }, 300)}
}})

此时,要拿到num和title的话,我们可以在组件中:

<template>
 <div>
    <h2>{{title}}</h2>
    <h3>{{num}}</h3>
 </div>
</template>

<script>
// 引入辅助函数mapState
import {mapState} from 'vuex'           //引入辅助函数
export default {
  // 在computed中引用
  computed: {
    ...mapState(['title', 'num'])       //引入数据
  }
};
</script>

如果打算从getters中取出num:

<h3>{{doubleNum}}</h3>

<script> 
import {mapState, mapGetters} from 'vuex'       //引入辅助函数
export default {
  computed: {
    ...mapState(['title']),                     //引入数据
    ...mapGetters(['doubleNum'])                //引入方法
  }
};
</script>

如果打算把mutations和actions中的方法引入:

<template>
 <div>
    <h2>{{title}}</h2>
    <h3>{{doubleNum}}</h3>
    <button @click="addNum(2)">累加2</button>
    <button @click="AsyncCutNum(2)">递减2</button>
 </div>
</template>

<script>
import {mapState, mapGetters, mapMutations, mapActions} from 'vuex'
methods: {
  	// 这里负责引入,我们把引入后的事件直接写在标签上,顺便把参数也带上
    ...mapMutations(['addNum']),
    ...mapActions(['AsyncCutNum'])
}
</script>

如果你必须把点击事件写在methods中,而不是标签上的话,你也可以这样:

<template>
 <div>
    <button @click="btnClick1">累加2</button>
    <button @click="btnClick2">递减2</button>
 </div>
</template>
 
<script>
import {mapState, mapGetters, mapMutations, mapActions} from 'vuex'
export default {
  methods: {
    ...mapMutations(['addNum']),                  //同步处理函数
    ...mapActions(['AsyncCutNum']),               //异步处理函数
    btnClick1(){
      // 直接通过this.xxx来调用辅助函数引入的事件
      this.addNum(2)          },                  //使用函数中的方法
    btnClick2(){
      this.AsyncCutNum(2)     }}                  //使用函数中的方法
};
</script>

六、Module 拆分模块

因为不同的函数可以单独抽调出来做成不同的模块,放入不同的文件夹,模块化后使得维护的打理更加迅速与高效

store下最大的index.js:

export default {
    state: {            
        num: 2           
    },
    getters: {
        doubleNum(state) {
            return state.num * 1;
        }
    },
    mutations: {
        addNum(state, payload) {
            state.num += payload;
        }
    },
    actions: {
        AsyncAddNum({ commit }, payload) {
            setTimeout(() => {
                commit('addNum', payload)
            }, 300)
        }
   modules: {      //仓库函数
    }
}

那么就把 addNum(state, payload)这个函数分出去放到add这个文件夹

store下最大的index.js:

import addNum from './add'            //引入addNum这个函数从 add这个文件夹中

export default new Vuex.Store({
     state: {             
        num: 2         
     },
     getters: {
        doubleNum(state) {
            return state.num * 1;
        }
     },                                  //可以看到此处已经没有mutations的存在了
     actions: {
        AsyncAddNum({ commit }, payload) {
            setTimeout(() => {
                commit('addNum', payload)
            }, 300)}
	modules: {
       addNum                            //此处来调用addNum使得他可以被组件中被使用
  }})

store下add这个文件夹的index.js:

export default {
    namespaced: true,     //命名空间,为true时,可以在store中把当前模块文件夹名称(add),当作模块名使用 命名空间的存在,人话:使得store中的其他文件夹的index.js能和总index,js产生关联,十分重要
    state: {},
    getters: {},
    mutations: {
        addNum(state, payload) {
           state.num += payload;
     }},
    actions: {},
}

七、拆分写法

实际上我们可以把state、getter、mutation、action和module全部都从store下的index.js中抽离出来,这样可以让store文件看着更加简洁。我们来将 store/index.js 进行拆分:

state.js

export default {
    num1: 0,
    title: '标题'
}

mutations.js

export default {
    cutNum(state, payload) {
        state.num1 -= payload;
    }
}

actions.js

export default {
    AsyncCutNum({ commit }, payload) {
        setTimeout(() => {
            commit('cutNum', payload)
        }, 300)
    }
}

modules.js

import add from './add'
export default {
    add
}

最后,在 store/index.js 中:

import Vue from 'vue'
import Vuex from 'vuex'                                 
import state from './state'             //同级的js文件   state.js
import mutations from './mutations'     //同级的js文件   mutations.js
import actions from './actions'         //同级的js文件   actions.js
import modules from './modules'         //同级的js文件   modules.js

Vue.use(Vuex)

export default new Vuex.Store({
  state,
  mutations,
  actions,
  modules
})
posted @ 2022-05-05 17:17  Dollom  阅读(32)  评论(0)    收藏  举报