vuex基本使用方法

82 阅读1分钟

vuex出现的原因:

由于状态零散地分布在许多组件和组件之间的交互中,大型应用复杂度也经常逐渐增长。为了解决这个问题,Vue 提供 vuex进行状态管理,负责组件间的通信。

vuex解决的问题:

1. 多个vue文件依赖同一个状态
2. 来自多个vue文件的事件变更同一个状态

vuex的基本使用方法:

State:在state中添加数据

{
  state: {
    name:'Tom',
    age: 999
  },
  getters: {
  },
  mutations: {
  },
  actions: {
  },
  modules: {
  }
}
vue文件获取state的方法一:

直接使用$store.state.属性

<template>
  <div>
    <div>{{ $store.state.name }}</div>
    <div>{{ $store.state.age }}</div>
  </div>
</template>
vue文件获取state的方法二:

使用mapState映射state数据到computed中

<template>
  <div>
    <div>{{ name }}</div>
    <div>{{ age }}</div>
  </div>
</template>
<script>
import { mapState } from "vuex";
export default {
  computed: {
    // 映射store到组件计算属性中,可直接使用
    ...mapState(['name', 'age'])
  },
};
</script>

Mutation:

store中的状态不能直接进行操作,我们使用mutation对store中的状态进行修改,便于监听数据的变化。

store中的状态必须通过Mutation的方法来处理。

{
  state: {
    name:'Tom',
    age: 999
  },
  getters: {
  },
  mutations: {
    changeName(state, newName) {
      state.name = newName;
    }
  },
  actions: {
  },
  modules: {
  }
}
vue文件使用mutation的方式一:

$store.commit()方式在methods方法中触发

<template>
  <div>
    {{ name }}
    <button @click="getMutation">触发mutations 方式1</button>
  </div>
</template>
import { mapState } from "vuex";
<script>
export default {
  computed: {
    // 映射store到组件计算属性中,可直接使用
    ...mapState(['name', 'age'])
  },
  methods: {
    // 触发mutation中的方法
    getMutation() {
       this.$store.commit('changeName', 'mutation 冲浪')
    },
  }
}
<script>
vue文件使用mutation的方式二:

使用mapMutations映射mutation方法到methods中

<template>
  <div>
    {{ name }}
    <button @click="changeName('mutation 浪啊')">触发mutation 方法2</button>
   </div>
</template>
<script>
import { mapState, mapMutation } from "vuex";
export default {
  computed: {
    // 映射store到组件计算属性中,可直接使用
    ...mapState(['name', 'age'])
  },
  methods: {
    // 映射mutation方法到组件methods中,可直接使用
    ...mapMutations(['changeName']),
  }
}
<script>

Action:

Action和Mutation的区别: Action处理的是异步任务,异步任务必须通过Action触发Mutation方法改变状态,不能直接使用Mutation直接对异步任务进行修改。

在Action中定义异步方法来调用Mutation的方法:

{
  state: {
    name:'Tom',
    age: 999
  },
  getters: {
  },
  mutations: {
    /**
     * @param {*} state 第一个参数 store中的状态(必须传递)
     * @param {*} newName 第二个参数传入
     */
    changeName(state, newName) {
      state.name = newName;
    }
  },
  actions: {
    /**
     * 
     * @param {*} context 上下文默认传递的参数
     * @param {*} newName 自己传的参数
     */
    // 定义一个异步的方法
    changeNameAsync(context,newName) {
      // 定时器模拟异步
      setTimeout(() => { 
        // 调用mutations中的方法
        context.commit('changeName', newName) 
      }, 2000)
    }
  },
  modules: {
  }
})
vue文件使用action的方式一:

this.$store.dispath()在methods方法中触发

<template>
  <div>
    {{ name }}
    <button @click="getAction('action 冲浪')">action 方式1</button>
   </div>
</template>
<script> 
import { mapState } from "vuex"; 
export default {
computed: { 
  // 映射store到组件计算属性中,可直接使用
  ...mapState(['name']) 
}, 
methods: { 
  getAction(newName){
    // dispath触发action中的方法 
    this.$store.dispath('changeNameAsync',newName)
  }
} 
}
<script>
vue文件使用action的方式二:

使用mapAction映射actions方法到methods中

<template>
  <div>
    {{ name }}
    <button @click="changeNameAsync('action 浪啊')">action 方式2</button>
   </div>
</template>
<script> 
import { mapState } from "vuex"; 
export default {
computed: { 
  // 映射store到组件计算属性中,可直接使用
  ...mapState(['name']) 
}, 
methods: { 
  // 映射actions方法到组件methods中,可直接使用
  ...mapAction(['changeNameAsync'])
} 
}
<script>

Getter:

Getter类似于计算属性,数据来源于Vuex中的State,Vuex中的数据需要简单包装处理由计算属性Getter来完成。

{
  state: {
    name:'Tom',
    age: 999
  },
  getters: {
    getterName(state) {
      return state.age + 1;
    }
  },
  mutations: {
    /**
     * @param {*} state 第一个参数 store中的状态(必须传递)
     * @param {*} newName 第二个参数传入
     */
    changeName(state, newName) {
      state.name = newName;
    }
  },
  actions: {
    /**
     * @param {*} context 上下文默认传递的参数
     * @param {*} newName 自己传的参数
     */
    // 定义一个异步的方法
    changeNameAsync(context, newName) {
      // 定时器模拟异步
      setTimeout(() => { 
        // 调用mutations中的方法
        context.commit('changeName', newName) 
      }, 2000)
    }
  },
  modules: {
  }
})
vue文件使用getter的方式一:

$store.getters.属性直接使用

<template>
  <div>
    {{ $store.getter.getterAge }}
   </div>
</template>
vue文件使用getter的方式二:

使用mapGetters映射getter方法到computed中

<template>
  <div>
    {{ getterAge }}
   </div>
</template>
<script> 
import { mapGetters } from "vuex"; 
export default {
  computed: {
    // 映射getter方法到组件计算属性中,可直接使用
    ...mapGetters(['getterAge'])
  },
}
<script>

Module:

Vuex由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。Vuex允许Store分成不同模块,每个模块都拥有自己的state,getter,mutation,action

新建一个tag 模块

export default {
  /**
   * 开启模块的命名空间,确保不同部分的代码可以使用相同的名称而不产生冲突。
   * @returns namespaced: true,
   */
  namespaced: true, // ❤❤注意:第一种方式时,不写入,第二种方式,写入
  state: () => ({
    defaultTime: '2023-09-01'
  }),
  mutations: {
    SET_DEFAULTTIME: (state, time) => {
      state.defaultTime = time;
    }
  }
}

在store/index.js中引入,挂载在modules

import tag from './modules/tagName'
  modules: {
    tag
  }
vue文件中使用方式一:

this.$store.state.tag.属性直接使用

<template>
  <div>
    {{ $store.state.tag.defaultTime }}
    <button @click="$store.commit('SET_DEFAULTTIME','2000-20-20')">tag 方法1</button>
   </div>
</template>
vue文件中使用方式二:

使用mapMutations映射mutation方法到methods中

<template>
  <div>
    <div>{{ defaultTime }}</div>
    <button @click="SET_DEFAULTTIME('1000-10-10')">tag 方法2</button>
 </div>
</template>
<script>
import { mapState, mapMutations } from "vuex";
export default {
  computed: {
    // mapState使用与之前不同,
    // 第一个参数Modules挂载的模块名,
    // 第二个参数tag模块中的属性名
    ...mapState('tag', ['defaultTime'])
  },
  methods: {
    // mapMutations使用与之前不同,
    // 第一个参数Modules挂载的模块名,
    // 第二个参数tag模块中的方法名
    ...mapMutations('tag', ['SET_DEFAULTTIME']),
  }
};
</script>