# vuex 使用
# Vuex 是什么?
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex 也集成到 Vue 的官方调试工具 devtools extension,提供了诸如零配置的 time-travel 调试、状态快照导入导出等高级调试功能。
# 什么是“状态管理模式”?
让我们从一个简单的 Vue 计数应用开始:
new Vue({
// state
data() {
return {
count: 0,
};
},
// view
template: `
<div>{{ count }}</div>
`,
// actions
methods: {
increment() {
this.count++;
},
},
});
# 什么情况下我应该使用 Vuex?
Vuex 可以帮助我们管理共享状态,并附带了更多的概念和框架。这需要对短期和长期效益进行权衡。
如果您不打算开发大型单页应用,使用 Vuex 可能是繁琐冗余的。确实是如此——如果您的应用够简单,您最好不要使用 Vuex。一个简单的 store 模式就足够您所需了。但是,如果您需要构建一个中大型单页应用,您很可能会考虑如何更好地在组件外部管理状态,Vuex 将会成为自然而然的选择。
# 开始
# 手摸手教你学会如何使用 Vuex
- 1、下载安装:npm install vuex --save
- 2、创建一个存储数据的仓库,为了方便管理我们可以在 src 目录下创建一个 store 目录,然后在里面创建数据仓库文件 index.js,具体代码如下:
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
//不是在生产环境debug为true
const debug = process.env.NODE_ENV !== 'production';
new Vuex.Store({
strict:debug,//在不是生产环境下都开启严格模式
// state为驱动应用的数据源
state: {
city: "北京",
},
});
export default Vuex.Store;
- 3、我们需要将该数据仓库 import 到 main.js 中使关键字“store”成为全局能使用的 API,具体代码如下:
import Vue from 'vue'
import App from './App'
import router from './router'
import store from './store/index'
Vue.config.productionTip = false/* eslint-disable no-new */new Vue({
el: '#app',
router,
store,
components: { App },
template: '<App/>'})
- 4、由于我们在 main.js 将 store 这个玩意加载到了 new Vue 实例中,因此我们要在组件中调用数据仓库中存储的数据那就十分简单,下面看示例代码:
<div class="header-right">
{{this.$store.state.city}}</div>
- 以上就是基础的 vuex 使用方式,下面我们需要实现的触发某事件,然后数据发生变化的操作,在开始看具体之前,先来琢磨一下官方给出的这张数据流向图:
结合这张图我们可知在组件中的数据是通过 dispatch 这个方法传递出去,核心代码实现如下:
//HTML代码,定义一个方法,在方法中派发一个changeCity事件,并传递参数<div class="title border-bottom">热门城市</div><div class="button-list">
<div class="button-wrapper" v-for="item of hot" :key="item.id" @click="handleCityClick(item.name)">
<div class="button">{{item.name}}</div>
</div></div>//Vue实例代码,通过dispatch派发成一个事件,并接收传值然后再传出去methods: {
handleCityClick (city) {
this.$store.dispatch('changeCity', city)
this.$router.push({
path: '/'
})
}}
继续看官网的数据流向图,可以知道此时数据来到了存储数据的仓库,此时的代码如下:
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
new Vuex.Store({
state: {
city: "上海",
},
actions: {
//ctx参数代表上下文,与mutations进行通信,city是组件传递过来的数据
//commit()方法的作用是将city数据传递给MchangeCity这个方法
changeCity(ctx, city) {
ctx.commit("MchangeCity", city);
},
},
});
export default Vuex.Store;
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
new Vuex.Store({
state: {
city: "上海",
},
actions: {
changeCity(ctx, city) {
ctx.commit("MchangeCity", city);
},
},
mutations: {
//state代表了最开始存放的区域,即驱动应用的数据源
MchangeCity(state, city) {
state.city = city;
},
},
});
export default Vuex.Store;
虽然以上就是完整的实现了组件之间数据联动的功能,但是事情还没结束呢,因为刷新页面时,数据还是会变回 state 中最初始的值,那么该怎么办呢?此时,就到了 HTML5 中的 localstorage 大显神威的时候了!下面请看具体代码,简直太简单了:
import Vue from 'vue'import Vuex from 'vuex'Vue.use(Vuex)export default new Vuex.Store({
state: {
city: localStorage.city || '上海'
},
actions: {
changeCity (ctx, city) {
ctx.commit('MchangeCity', city)
}
},
mutations: {
MchangeCity (state, city) {
state.city = city
localStorage.city = city }
为了避免用户将浏览器的本地存储关闭而导致的错误使网站奔溃,我们应该编写以下更加合理的代码:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
let defaultcity = '上海'try {
if (localStorage.city) {
defaultcity = localStorage.city }} catch (e) {}export default new Vuex.Store({
state: {
city: defaultcity },
actions: {
changeCity (ctx, city) {
ctx.commit('MchangeCity', city)
}
},
mutations: {
MchangeCity (state, city) {
state.city = city try {
localStorage.city = city } catch (e) {}
}
}})
export {defaultcity}
其实对于 vuex 数据的传递,我们还有一个简洁的方法,就是定义一个数组项来映射 vuex 中的数据,使 HTML 代码中调用数据的代码量减少,同时方便管理,下面看具体代码:
<!-- {{this.$store.state.city}}变成了this.city -->
<div class="header-right">
{{this.city}}</div><script>import { mspState } from 'vuex'export default {
name: 'HomeHeader',
computed: {
...mapState(['city'])
}}</script><script>//我们也能传递个对象过去//此时this.city就要变成this.currentCity了import { mspState } from 'vuex'export default {
name: 'HomeHeader',
computed: {
...mapState({
currentCity: 'city'
})
}}</script>
# Vuex 中跳过 actions 的用法
我们在应用 vuex 的时候还可以将 actions 这个步骤直接忽略掉,使代码变得更加简洁
// 组件代码
let status = sessionStorage.getItem("systemStatus");
this.$store.commit('systemSta', status);
// vuex文件代码
state: {
systemStatus: ""},
mutations: {
systemSta(state, value) {
state.systemStatus = value;
}
}
// 另一个组件代码
let status = this.$store.state.systemStatus;
以上关于 Vuex 的内容整理几乎都是大白话式的,为了更好的深入理解和学习 Vuex,请立刻前来官方网站
# 辅助函数:
- 引入辅助函数,从同一个库中引入多个的时候使用大括号
- 大括号里面的没有顺序之分
# 使用步骤
1:导入
import {mapState,mapGetters,mapActions,mapMutations} from 'vuex'
2:store文件夹中的index.js 文件中
export default new Vuex.Store({
state:{
count:0,
num:100
},
getters:{
changeState(state){
return state.count/4
}
},
actions:{
acCountAdd({commit},val){
commit('muCountAdd',val)
},
acCountMinus({commit},val){
commit('muCountMinus',val)
},
},
mutations:{
muCountAdd(state,val){
state.count+=val
},
muCountMinus(state,val){
state.count-=val
}
},
})
3:组件内写法
computed:{
// 使用state辅助函数,使用对象方式时,名称可以不一致
...mapState({
count:state=>state.count
}),
// 使用getters辅助函数,使用对象方式时,名称可以不一致
...mapGetters({
changeState:'changeState'
})
},
methods: {
// 使用mutations辅助函数,使用对象方式时,名称可以不一致
...mapMutations({
muCountAdd:'muCountAdd'
}),
// 使用actions辅助函数,使用对象方式时,名称可以不一致
...mapActions({
acCountAdd:'acCountAdd'
})
},
辅助函数:mapState,mapGetters,mapActions,mapMutations
1.mapState:映射state中的数据到this.data上,
vuex的state,getters,使用辅助函数映射过来要放在computed中
写法:...mapState([]),映射的每一条数据都是字符串
...mapState({,穿对象的时候能给映射的数据起别名
别名:箭头函数的返回值就是别名的值,state作为参数的函数返回值
})
2.mapGetters:映射getters中的数据到this.data上
写法:...mapGetters([]),不需要起别名的时候数组作为参数,把映射过来的数据作为数组中的字符串
...mapGetters({}),需要起别名的时候对象作为参数,对象中的key是别名,value是原名,原名是字符串
3.mapActions:映射actions中的函数到组件的methods上
mapActions,mapMutations映射过来的函数放在methods中
写法:...mapActions([]),参数为数组的时候不能起别名,函数名作为参数数组的每一项
...mapActions({
key:value key是别名,value是原名,原名是字符串
})
4.mapMutations:把mutations中的函数映射到methods中
写法:...mapMutations([]),参数为数组的时候不能起别名,数组里面的每一项都是函数名字符串
...mapMutations({
key:value key是别名,value是原名
})