前言
说到 vuex 相信大家都不陌生,vuex 是一个专为 vue.js 应用程序开发的状态管理模式。vuex 背后的基本思想,就是单向数据流。今天我们就来好好聊聊 vuex。
vuex?
用官方的话来说,vuex
是一个专为 vue.js
应用程序开发的状态管理模式 + 库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
状态管理?
状态就是数据。状态管理可以简单理解为把需要多个组件共享的变量全部存储在一个对象里面。然后将这个对象放在顶层的 vue
实例中,让其他组件可以使用。通过使用 vuex
可集中管理组件之间的数据(状态),使组件之间的数据共享变得简单。
如何安装 vuex?
1. 通过
npm
方式安装。
npm i vuex --save
npm i vuex@3.6.2 --save //安装特定版本
yarn add vuex //yarn安装方式
2. 在
main.js
中引入,然后挂载到Vue
实例里。
import Vue from 'vue'
import store from './store'
new Vue({
render: h => h(App),
store
}).$mount('#app')
3. 在
scr
目录下创建一个store/index.js
文件,写入以下内容。
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const state = {}
const getters = {}
const mutations = {}
const actions = {}
export default new Vuex.Store({
state,
getters,
mutations,
actions,
})
vuex 的核心
一、state
state
简单来说就是一个状态,用户界面会随着 state
变化而变化。
栗子:
store/index.js
文件
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const state = {
name: "金闯",
age: 18,
count: 0
}
const getters = {}
const mutations = {}
const actions = {}
export default new Vuex.Store({
state,
getters,
mutations,
actions,
})
任意
.vue
文件中使用
<template>
<div>
<h5>姓名:{{$store.state.name}}</h5>
<h5>年龄:{{$store.state.age}}</h5>
<h5>工龄:{{$store.state.count}}</h5>
</div>
</template>
页面效果
使用语法糖辅助函数(mapState)⤵
二、getter
getter
就是一个计算属性。对 state
数据进行计算(会被缓存),类似于 vue
组件中的 computed
,对 state
里的数据进行一些过滤、改造等等,例如我们要在 state.count
的基础上派生出一个新的状态 newCount
出来,就适合使用 getter
属性。
栗子:
store/index.js
文件
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const state = {
count: 5
}
const getters = {
newCount: state => state.count * 6
}
const mutation = {}
const actions = {}
export default new Vuex.Store({
state,
getters,
mutation,
actions,
})
任意
.vue
文件中使用
<template>
<div>{{newCount}}</div>
</template>
<script>
export default {
computed: {
newCount() {
return this.$store.getters.newCount;
},
},
};
</script>
页面效果
使用语法糖辅助函数(mapGetters)⤵
三、mutation
mutation
就是改变状态,唯一可修改 state
数据的场所。
栗子:
store/index.js
文件
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const state = {
count: 0
}
const getters = {}
const mutations = {
addWay(state, num) {
state.count = state.count + num;
console.log(state.count);
},
minusWay(state) {
state.count--;
console.log(state.count);
},
}
const actions = {}
export default new Vuex.Store({
state,
getters,
mutations,
actions,
})
任意
.vue
文件中使用
<template>
<div>
<el-button @click="addOn">加</el-button>
<el-button @click="minusOn">减</el-button>
</div>
</template>
<script>
export default {
methods: {
addOn() {
this.$store.commit("addWay", 1); //每次+1
},
minusOn() {
this.$store.commit("minusWay");
},
},
};
</script>
页面效果
使用语法糖辅助函数(mapMutations)⤵
四、action
action
就是一个异步操作,提交 mutation
执行异步操作(不是直接变更状态)。主要是用来解决异步流程来改变 state
数据。因为 mutation
是同步操作,如果你在 mutation
里进行异步操作,你会发现并不会起任何效果,故只能通过 action=>mutation=>state
流程修改。
栗子:
store/index.js
文件
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const state = {
count: 0
}
const getters = {}
const mutations = {
minusWay(state) {
state.count--;
console.log(state.count);
},
}
const actions = {
asyncAdd(context) {
setTimeout(() => {
context.commit("minusWay")
}, 500)
}
}
export default new Vuex.Store({
state,
getters,
mutations,
actions,
})
任意
.vue
文件中使用
<template>
<div>
<el-button @click="minusOn">减</el-button>
</div>
</template>
<script>
export default {
methods: {
minusOn() {
this.$store.dispatch("asyncAdd"); //dispatch触发action函数
},
},
};
</script>
页面效果
使用语法糖辅助函数(mapActions)⤵
五、modules
vuex
允许我们将 store
分割到模块。目的是为了让代码更好维护,让多种数据分类更加明确,每个模块都拥有独立的 state、mutation、action、getter
,甚至是嵌套子模块从上至下进行类似下面的拆分:
const moduleA = {
state: {},
mutations: {},
actions: {},
getters: {},
}
const moduleB = {
state: {},
mutations: {},
actions: {},
getters: {},
}
const store = new Vue.store({
modules: {
moduleA,
moduleB
}
})
vuex 辅助函数(语法糖)
辅助函数可以把 vuex
中的数据和方法映射到 vue
组件中。达到简化操作的目的。
一、mapState(state)
栗子:
<template>
<div>
<!-- 直接使用 -->
<h5>姓名:{{name}}</h5>
<h5>年龄:{{age}}</h5>
<h5>工龄:{{count}}</h5>
</div>
</template>
<script>
import { mapState } from "vuex"; //从vuex中按需导入mapstate函数
export default {
// 辅助函数使用
computed: {
...mapState(["name", "age", "count"]),
},
};
</script>
二、mapGetters(getter)
栗子:
<template>
<div>{{newCount}}</div>
</template>
<script>
import { mapGetters } from "vuex"; //从vuex中按需导入mapGetters函数
export default {
computed: {
...mapGetters(["newCount"]),
},
};
</script>
三、mapMutations(mutation)
栗子:
<template>
<div>
<el-button @click="addOn">加</el-button>
<el-button @click="minusOn">减</el-button>
</div>
</template>
<script>
import { mapMutations } from "vuex"; //从vuex中按需导入mapMutations函数
export default {
methods: {
...mapMutations(["addWay", "minusWay"]),
addOn() {
this.addWay(1); //直接调用
},
minusOn() {
this.minusWay();// 直接调用
},
},
};
</script>
四、mapActions(action)
栗子:
<template>
<div>
<el-button @click="minusOn">减</el-button>
</div>
</template>
<script>
import { mapActions } from "vuex"; //从vuex中按需导入mapActions函数
export default {
methods: {
...mapActions(["asyncAdd"]),
minusOn() {
this.asyncAdd(); // 直接调用
},
},
};
</script>