Vue总结(六)——Vuex进阶

文章目录

  • Vue总结(六)——Vuex进阶
    • 前言
    • 1、getters
      • 1.2 基本使用
      • 1.3 示例
    • 2、mapState 与 mapGetters
      • 2.1 基本用法
      • 2.2 示例
    • 3、mapMutations 和 mapActions
      • 3.1 基本用法
      • 3.2 示例
    • 4、多组件共享数据
    • 5、模块化 + 命名空间(重要)
      • 5.1 基本使用
      • 5.2 示例
        • 5.2.1 代码抽离
          • src/store/count.js
          • src/store/person.js
          • src/store/index.js
        • 5.2.2 页面编写
          • Count.vue
          • Person.vue

Vue总结(六)——Vuex进阶

前言

这篇博客是在上一篇博客的基础上,再进一步进行总结的。所以建议先看一下上一篇博客。

上一篇:Vue总结(五)——Vuex入门

这篇博客主要的内容包括:

  1. getters
  2. mapState 与 mapGetters
  3. mapMutations 和 mapActions
  4. 案例:多组件共享数据
  5. vuex 模块化编码

1、getters

1.2 基本使用

  1. 概念:当state中的数据需要经过加工后再使用时,可以使用getters加工(getters类似于计算属性)。

  2. src/store/index.js中追加getters配置

    ......
    
    const getters = {
    	bigSum(state){
    		return state.sum * 10
    	}
    }
    
    //创建并暴露store
    export default new Vuex.Store({
    	......
    	getters
    })
    
  3. 组件中读取数据:$store.getters.bigSum

1.3 示例

改造上一篇博客的【求和案例】,getter实现。

  • 点击“+”号,sum进行加1
  • 点击“-”号,sum进行减1
  • 点击“当前求和为奇数再加”,如果sum当前为奇数,sum就加1,否则保持不变
  • 点击“等一等再加”,则等几秒钟sum才会加1
  • 新增功能
    • 当前求和(sum值)放大10倍

src/store/index.js

//该文件用于创建Vuex中最为核心的store
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
//应用Vuex插件
Vue.use(Vuex);

//准备actions——用于响应组件中的动作
const actions = {
    //如果不用进行业务处理,可以直接绕过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
})

src/main.js

注册store配置对象。

//引入Vue
import Vue from 'vue'
//引入App
import App from './App.vue'
//引入store
import store from './store'
//关闭Vue的生产提示
Vue.config.productionTip = false;

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

src/components/Count.vue






App.vue





2、mapState 与 mapGetters

2.1 基本用法

要使用,先引入对应的组件

import {mapState, mapGetters} from 'vuex'
  1. mapState方法:用于帮助我们映射state中的数据为计算属性(生成state中数据的计算属性)

    computed: {
        //借助mapState生成计算属性:sum、school、subject(对象写法)
         ...mapState({sum:'sum',school:'school',subject:'subject'}),
             
        //借助mapState生成计算属性:sum、school、subject(数组写法)
        ...mapState(['sum','school','subject']),
    },
    
  2. mapGetters方法:用于帮助我们映射getters中的数据为计算属性(生成getters中数据的计算属性)

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

2.2 示例

src/store/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







对象里面写对象,采取以下方式实现:

…mapGetters({bigSum:‘bigSum’})

  1. 拓展运算符(…)用于取出参数对象所有可遍历属性,然后拷贝到当前对象(里面的对象按属性或值展开,放到外层对象)
  2. 扩展运算符能将【数组】或【对象】转换为逗号分隔的参数序列
  3. 用拓展运算符做了解构

3、mapMutations 和 mapActions

3.1 基本用法

要使用,先引入对应的组件

import {mapState, mapGetters} from 'vuex'
  1. mapActions方法:用于帮助我们生成与actions对话的方法,即:包含$store.dispatch(xxx)的函数

    methods:{
        //靠mapActions生成:incrementOdd、incrementWait(对象形式)
        ...mapActions({incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
    
        //靠mapActions生成:incrementOdd、incrementWait(数组形式)
        ...mapActions(['jiaOdd','jiaWait'])
    }
    
  2. mapMutations方法:用于帮助我们生成与mutations对话的方法,即:包含$store.commit(xxx)的函数

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

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

3.2 示例

src/store/index.js

和【2.2 示例】的src/store/index.js一样,此处略写。

Count.vue







4、多组件共享数据

案例:

  • 求和,将sum展示到其他组件。
  • 添加人员,将人员列表人数展示到其他组件。

src/store/index.js

//该文件用于创建Vuex中最为核心的store
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
//应用Vuex插件
Vue.use(Vuex);

//准备actions——用于响应组件中的动作
const 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——用于操作数据(state)
const mutations = {
    JIA(state, value) {
        console.log('mutations中的JIA被调用了');
        state.sum += value
    },
    JIAN(state, value) {
        console.log('mutations中的JIAN被调用了');
        state.sum -= value
    },
    //添加一个Person到列表
    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
})

src/main.js

//引入Vue
import Vue from 'vue'
//引入App
import App from './App.vue'
//引入store
import store from './store'
//关闭Vue的生产提示
Vue.config.productionTip = false;

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

Count.vue







Person.vue





App.vue






5、模块化 + 命名空间(重要)

5.1 基本使用

  1. 目的:让代码更好维护,让多种数据分类更加明确。

    1. 说白了就是代码抽离、解耦。
  2. 修改src/store/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
      }
    })
    
  3. 开启命名空间后,组件中读取state数据:

    //方式一:自己直接读取
    this.$store.state.personAbout.list
    //方式二:借助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',person)
    //方式二:借助mapActions:
    ...mapActions('countAbout',{incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
    
  6. 开启命名空间后,组件中调用commit

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

5.2 示例

5.2.1 代码抽离

步骤:

  1. src/store/index.js中的代码,按业务拆分成多套配置(多个对象);
  2. 每套配置都可以包含 actions、mutations、state、getters;
  3. 然后再进一步把代码抽离,把多套配置放在不同的js文件中;
  4. 最后,在src/store/index.js中通过 import 进行配置导入。
src/store/count.js
//求和相关的配置
export default {
    namespaced: true, //开启命名空间后,和store中的modules里的key对应,简化组件中读取state数据的步骤
    actions: {
        //sum为奇数再加1
        jiaOdd(context, value) {
            console.log('actions中的jiaOdd被调用了')
            if (context.state.sum % 2) {
                context.commit('JIA', value)
            }
        },
        //等一等再加1
        jiaWait(context, value) {
            console.log('actions中的jiaWait被调用了')
            setTimeout(() => {
                context.commit('JIA', value)
            }, 500)
        }
    },
    mutations: {
        //直接加1
        JIA(state, value) {
            console.log('mutations中的JIA被调用了')
            state.sum += value
        },
        //直接减1
        JIAN(state, value) {
            console.log('mutations中的JIAN被调用了')
            state.sum -= value
        },
    },
    //对数据进行存储
    state: {
        sum: 0, //当前的和
        school: '哈麻皮',
        subject: '后端',
    },
    //对数据进一步加工,作用和计算属性类似
    getters: {
        bigSum(state) {
            return state.sum * 10
        }
    },
}

备注:

namespaced: true,

开启命名空间后,和store中的modules里的key对应,简化组件中读取state数据的步骤。

src/store/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: {
        //添加一个Person到列表
        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
        }
    },
}

备注:

namespaced: true,

开启命名空间后,和store中的modules里的key对应,简化组件中读取state数据的步骤。

src/store/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, //key : value
        personAbout: personOptions
    }
})

5.2.2 页面编写

步骤:

  1. 自动生成或者手动编写对应的计算属性和对应的函数,
  2. 在页面上使用自动生成的,或者手动编写好的计算属性和函数即可。
Count.vue

采用 mapState, mapGetters, mapMutations, mapActions 来自动生成对应的计算属性,

以及自动生成,调用commit去联系Mutations的函数,和调用dispatch去联系actions的函数等;

并采用模块化开发。







备注:

…mapState(‘countAbout’, [‘sum’, ‘school’, ‘subject’]),

  1. 借助mapState生成计算属性,从state中读取数据。(数组写法)
  2. 自动生成 countAbout 这套配置中,state数据的计算属性。

…mapMutations(‘countAbout’, {increment: ‘JIA’, decrement: ‘JIAN’}),

  • 借助mapMutations生成对应的方法,方法中会调用commit去联系mutations(对象写法)
  • 自动生成 countAbout 这套配置中,对应的函数,函数中commit去联系mutations。

页面上直接调用对应的函数,或计算属性即可。

Person.vue

自己手动编写state对应的计算属性,以及自己编写,

调用commit去联系Mutations的函数和调用dispatch去联系actions的函数等;

并采用模块化开发。





备注:

this.$store.getters[‘personAbout/firstPersonName’]

  1. 调用personAbout这套配置中,getters中,值为firstPersonName的函数;
  2. 调用哪套配置中getters的哪个函数,中间用 “/” 隔开,并且外面用数组包裹。

$store.commit(‘personAbout/ADD_PERSON’, personObj)

  • 调用personAbout这套配置中,mutations中,名称为ADD_PERSON的函数,传递的参数是personObj;
  • 调用哪套配置中mutations的哪个函数,中间用 “/” 隔开,作为commit的第一个参数,commit的第二个参数维传递给函数的值;并且外面用()包裹。

页面上直接调用对应的函数,或计算属性即可。

Vue的内容整理到这里就结束了,欢迎留言交流。

你可能感兴趣的:(前端,vue.js,前端,vue)