Vuex的复习|【青训营笔记】

65 阅读2分钟

这是我参与「第四届青训营 」笔记创作活动的第15天

今天来复习一下Vuex的使用

  • 概念:专门在Vue中实现集中式状态(数据)管理的一个Vue插件,对vue应用中的多个组件的共享状态进行集中式的管理(读/写),也是一种组件金童新的方式,且适用于任意组件间通信。
  • 何时使用:多个组件需要共享数据时
(1)搭建vuex环境

1.创建文件: 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
 })

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

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

使用方法:

在组件中调用dispatch()或直接commit()

 increase () {
      this.$store.commit('INCREASE',this.n)
     },
     decrease () {
      this.$store.commit('DECREASE',this.n)
     },
     odd_increase () {
     this.$store.dispatch('odd_increase',this.n)
     },
     wait_increase () {
       setTimeout(()=>{
        this.$store.dispatch('wait_increase',this.n)
       },2000)
     }
     }

在store文件夹下index.js中的actions书写逻辑,mutation进行数据变换,state中写入原始数据

注意: 组件中修改数据:this.store.dispatch(actions中的方法,数据),或this.store.dispatch('actions中的方法名',数据),或this.store.commit('mutations中的方法名',数据)。若没有网络请求或业务逻辑,组件也可以越过actions,即不写dispatch(),直接commit()。

 const actions={
   odd_increase(context, value) {
        if (state.sum % 2) {
       context.commit('ODD_INCREASE',value) }
     },
   wait_increase(context, value) {
       context.commit('WAIT_INCREASE',value)
     }
 }
 -----------------------------------------------------------------------
 const mutations={
     INCREASE(state, value) {
     state.sum+=value
   },
 ​
   DECREASE(state, value) {
     state.sum-=value
   },
   ODD_INCREASE(state, value) {
       state.sum+=value
    
   },
   WAIT_INCREASE(state, value) {
     state.sum+=value
   }
 }
 ---------------------------------------------------------------------------
 const  state={
     sum:0
 }

在组建中使用Vuex中存储的数据

    <h1>当前的值为:{{$store.state.sum}}</h1>

注意组件模板中可以直接使用store.state.sum,而js中要使用this.store.state.sum,而js中要使用this.store.state.sum

(2)getters的使用
  • 1.概念:当state中的数据需要加工后再使用,可以使用getters

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

     const getters={
       bigSum(state){
         return state.sum*10
       }
     }
     ----------------------
     export default new Vuex.Store({
         actions,
         mutations,
         state,
         getters
     }
    
  • 3.组件中读取数据:$store.getters.bigSum

(3)四个map方法的使用

使用这些方法前需要导入:import {mapState,mapGetters,mapActions,mapMutations} from 'vuex'

用那个导入那个

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

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

 computed:{
   // 借助mapGetters生成计算属性:sum,school,subject (对象写法)
   ...mapGetters({bigSum:'bigSum'})
     
      // 借助mapGetters生成计算属性:sum,school,subject (数组写法)
   ...mapGetters(['bigSum'])
 }
  • mapActions方法:用于帮助我们生成与actions对话的方法,即包含$store.dispatch(xxx)的函数
 methods:{
    // 借助mapActions生成odd_increase,wait_increase(对象写法)
    ...mapActions({odd_increase:'odd_increase',wait_increase:'wait_increase'})
     
   // 借助mapActions生成odd_increase,wait_increase(数组写法)
    ...mapActions(['odd_increase','wait_increase'])
 }
 ​
 当mapActions,mapMutations使用时,若需要传递参数:要在模板绑定事件的回调函数中传递好参数,否则会将默认的event事件对象当成参数传递,引起错误。
 <button @click="odd_increase(n)">当前和为奇数才加</button>
  • mapMutations方法:用于帮助我们生成与mutations对话的方法,即包含$store.commit(xxx)的函数
 methods:{
    // 借助mapMutations生成INCREASE,DECREASE(对象写法)
    ...mapMutations({INCREASE:'INCREASE',DECREASE:'DECREASE'})
     // 借助mapMutations生成INCREASE,DECREASE(数组写法)
    ...mapMutations(['INCREASE','DECREASE']) 
     
 }
 注意当这些方法需要传递参数时,应在调用生成的方法是进行手动传参:
 <button @click="INCREASE(n)">+</button>
 <button @click="DECREASE(n)">-</button>
 谨记:数组写方法中的名字有两个作用 ------
 1.作为包含$store.commit的函数方法名
 2.作为store文件夹下index.js文件中mutations中对应的方法名
 ​

(4)vuex的模块化开发

多个组件的actions,mutations,state,getters在一起,代码冗余在一起,不利于维护

将上方例子模块化:

  • 将Count,Person组件的actions,mutations等写在不同的对象或文件中
 const CountOptions = {
     namespaced:true,
     actions : {
     //准备actions——用于响应组件中的动作
     odd_increase(context,value){
         console.log('actions中的jiaOdd被调用了')
         if(context.state.sum % 2){
             context.commit('INCREASE',value)
         }
     },
     wait_increase(context,value){
         console.log('actions中的jiaWait被调用了')
         setTimeout(()=>{
             context.commit('INCREASE',value)
         },500)
     }
     },
     //准备mutations——用于操作数据(state)
     mutations: {
         INCREASE(state, value) {
             console.log('mutations中的JIA被调用了')
             state.sum += value
         },
         DECREASE(state, value) {
             console.log('mutations中的JIAN被调用了')
             state.sum -= value
         }
     },
   //准备state——用于存储数据
   state : {
     sum:0, //当前的和
     school:'尚硅谷',
     subject:'前端',
   },
   //准备getters——用于将state中的数据进行加工
   getters : {
     bigSum(state){
         return state.sum*10
     }
   } 
 }
 --------------------------------------------------------------------------------------------------------
 const PersonOptions = {
     namespaced:true,
     actions: {
         // 添加姓王的人名
         add_wang(context, value) {
             if (value.name.indexOf('王') === 0) {
                 context.commit('ADD_PERSON',value)
             } else {
                 alert('人名必须姓王')
             }
         },
         randomadd(context) {
             axios.get('https://api.uixsj.cn/hitokoto/get?type=social').then(
                 response => {
                     context.commit('ADD_PERSONSERVER', {id:nanoid(),name: response.data })
                 },
                 error => {
                     alert(error.message)
                 }
             )
         }
     },
     mutations: {
         ADD_PERSON(state, value) {
             console.log('mutations中的ADD_PERSON被调用了')
             state.personList.unshift(value)
         },
         ADD_PERSONSERVER(state,value) {
             state.personList.push(value)
         }
     },
     state: {
         personList:[
         {id:'001',name:'张三'}
     ]   
     },
     getters: {
         fristListName(state) {
             return state.personList[0].name
         }
     }
     }
  • 声明空间namespaced和导出时模块化
 建立组件对象时加上namespaced:true
 导出时利用modules{}
 //创建并暴露store
 export default new Vuex.Store({
     modules: {
         Countabout: CountOptions,
         Personabout: PersonOptions
     },
     
 })
  • 使用state数据,调用action,mutations,getters方法的方式

使用map方法简写时: ...mapxxx('模块组件名',['属性'])

   computed:{
     ...mapState('Countabout',{he:'sum',xuexiao:'school',xueke:'subject'}) //(对象写法)
     ...mapState('Countabout',['sum','school','subject']), // (数组写法)
     ...mapState('Personabout',['personList']),
     ...mapGetters('Countabout',['bigSum'])
   },
   methods:{
     ...mapActions('Countabout',['odd_increase','wait_increase']),
     ...mapMutations('Countabout',['INCREASE','DECREASE'])
   }

直接this.$store.xxx时:this.$store.xxx('模块组件名/方法名',‘数据’) this.$store.xxx.模块组件名.属性

  this.$store.dispatch('Personabout/k',personObj)   
  this.$store.commit('Personabout/ADD_PERSON',personObj)
  computed:{
   personList(){
     return this.$store.state.Personabout.personList
   },
   sum(){
     return this.$store.state.Countabout.sum
   },
   fristListName(){
     return this.$store.getters['Personabout/fristListName'] //要使用对象的第二种取属性方法 obj['属性名']
   }
 },