Vuex
Vuex是什么
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化,以利用 Vue.js 的细粒度数据响应机制来进行高效的状态更新。
安装与配置uex
安装
// 三种方式都可以
npm install vuex --save
yarn add vuex
cnpm install -save vuex
配置
在src
目录下创建一个store
文件夹,并在该文件夹下创建index.js
文件:
// src/store/index.js文件
import Vue from 'vue'
import Vuex from 'vuex';
Vue.use(Vuex);
export default new Vuex.Store({
state:{}
})
同时将该文件导入main.js
文件中:
// src/main.js文件
import store from './store';
// Vue实例化这里把 store 加入进去
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app');
如果是创建全新的vue工程,只需要在创建过程中选择自定义配置,并勾选
Babel、Router、Vuex、Linter\Formatter
即可。
项目结构
使用Vuex需要遵守的规则:
-
应用层级的状态应该集中到单个
store
对象中。 -
提交
mutation
是更改状态的唯一方法,并且这个过程是同步的。 -
异步逻辑都应该封装到
action
里面。
如果你的 store 文件太大,只需将 action 、mutation 和 getter 分割到单独的文件:
├── pages
├── static
└── store
├── index.js # 我们组装模块并导出 store 的地方
├── actions.js # 根级别的 action
├── mutations.js # 根级别的 mutation
└── modules # 模块文件夹
├── cart.js # 购物车模块
└── products.js # 产品模块
├── App.vue
├── main.js
├── manifest.json
├── pages.json
└── uni.scss
Satte、Mutation、Action
State
State
的作用就是用来储存数据的,因为Vuex是状态管理框架,所以在Vuex中state就是表示数据在Vuex中的储存状态,可以看作一个全局的大Json对象,而且如果我们想要获取数据只能从 state 中获取。
Mutation
Mutation
的作用就是修改State
中的状态,State 中的数据不能直接被修改,如果需要修改其中的状态值,则只能通过 Mutation 进行修,Mutation 是一个函数,接收两个参数:
- state:当前上下文中的 state 实例;
- payload:接收外部传入的对象,需要和调用方约定好对象类型,也可以不传入;
// 一个简单的Vue计数应用
export default new Vuex.Store({
state: {
count: 0
},
mutations: {
increment(state) {
state.count++;
},
decrement(state) {
state.count--;
}
}
});
Action
Vuex对数据的管理十分严格,除了必须通过Mutation
来进行State
的状态修改之外,还不允许外部调用Mutation
的函数,如果想要修改State
中的状态,则需要通过Action
来触发Mutation
中的函数进行修改:
export default new Vuex.Store({
state: {
count: 0
},
actions: {
increment: ({ commit }) => commit('increment'),
decrement: ({ commit }) => commit('decrement')
},
mutations: {
increment(state) {
state.count++;
},
decrement(state) {
state.count--;
}
}
});
commit
commit 是一个函数,它的作用就是将数据提交到 mutation 中去,他有两个参数:
- 第一个参数是 mutation 中的函数名称;
- 第二个参数是自定义的对象
export default new Vuex.Store({
state: {
users: []
},
actions: {
load: async ({commit}) => {
const response = await axios.get("https://www.fastmock.site/mock/a9b15cd4db90d4e03ed76cd3c76d9197/f6/users");
// 这里第二个参数就是下面的 payload
commit("load",response.data.data.users);
}
},
mutations: {
load(state,payload) {
state.users = payload;
}
}
});
使用Vuex Store
获取state
,在 vue 文件中的任何位置都可以使用$store.state.count
来获取state
中的状态,而在实际工作中我们很少使用这种方式,而是借助 Vuex 中的 mapState 这个函数,动态的将 state 和 computed 绑定:
// Counter.vue 文件中
<template>
<div>
Clicked: {{ count }} times
</div>
</template>
<script>
// 导入 mapState 函数
import { mapState } from 'vuex';
export default {
computed: {
...mapState({
// 箭头函数可使代码更简练
count: state => state.count
})
}
};
</script>
执行 store 的 action
我们通过 Vuex 中的 mapActions 这个函数把 store 中的 action 动态的绑定到 vue 中的 methods 对象里面:
// Counter.vue 文件中
<template>
<div>
Clicked: {{ count }} times
<div>
<button @click="increment">+</button>
<button @click="decrement">-</button>
</div>
</div>
</template>
<script>
// 导入 mapState mapActions 函数
import { mapState, mapActions } from 'vuex';
export default {
computed: {
...mapState({
count: state => state.count
})
},
methods: { ...mapActions(['increment', 'decrement']) }
};
</script>
Getter
Vuex 中的 Getter 函数类似 Vue 中的 computed 函数的作用,Getter 的返回值会根据他的依赖被缓存起来,且只有当他的依赖值发生变化时才会被重新计算。
定义Getter
Getter 接受 state 作为他的第一个参数:
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
export default new Vuex.Store({
state: {
count: 0
},
actions: {
increment: ({ commit }) => commit("increment"),
decrement: ({ commit }) => commit("decrement")
},
mutations: {
increment(state) {
state.count++;
},
decrement(state) {
state.count--;
}
},
getters: {
evenOrOdd: state => (state.count % 2 === 0 ? "偶数" : "奇数")
}
});
使用Getter
类似 state 的使用,我们可以借助 mapGetters 函数将其解构放入 computed 中:
import { mapGetters } from 'vuex'
export default {
// ...
computed: {
// 使用对象展开运算符将 getter 混入 computed 对象中
...mapGetters([
'evenOrOdd'
])
}
}
Vuex request
// store/index.js 文件中
import Vue from "vue";
import Vuex from "vuex";
import axios from "axios";
Vue.use(Vuex);
export default new Vuex.Store({
state: {
// 用于储存请求的数据
users: []
},
actions: {
// 网络请求是一个异步行为,所以需要使用 async\await
load: async ({ commit }) => {
// 使用 axios 框架进行网络请求,使用 get 就可以获取到数据了
const response = await axios.get(
"https://www.fastmock.site/mock/a9b15cd4db90d4e03ed76cd3c76d9197/f6/users"
);
// 上面请求返回的是一个 http response 对象,要获取其中的内容需要读取其 data 属性
// 再对比一下 api 返回的数据
commit("load", response.data.data.users);
}
},
mutations: {
load(state, payload) {
state.users = payload;
}
}
});
完成上面store
的配置之后,需要在vue文件中添加:
// User.vue 文件
<script>
import { mapState, mapActions } from "vuex";
export default {
async mounted() {
// 在这个 vue 的生命周期中调用 load 函数
await this.load();
},
computed: {
...mapState({
users: state => state.users
})
},
methods: { ...mapActions(["load"]) }
};
</script>