Vuex
1.Vuex 介绍
Vuex 是一个专为Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex 也集成到 Vue 的官方调试工具,提供了诸如零配置的 time-travel 调试、状态快照导入导出等高级调试功能。
###1. 为什么要使用 Vuex?
为了实现复杂层级的组件间数据传递、共享
- Vuex 是一个专为 Vue.js 应用程序开发的集中式的状态(数据)管理的工具。
- Vuex 最主要去做的事情就是 实现 组件与组件之间的数据传递。
###2. Vue**基础学习的组件通信有哪些?
- 父传子 : props
- 子传父 : $emit
- 兄弟组件之间的数据传递 : eventBus 事件中心
3.vuex 核心内容
state: state 是一个对象,所有 Vuex 的数据都会保存在 state 中。mutations: 所有要放到 state 的数据,不能直接放进去,必须通过 mutations 来放进去actions: 专门用来处理异步操作的东西。
2.vuex 基础使用
- 下包
yarn add vuex
- 导入到 main.js
improt Vuex from 'vuex';
- 全局注册
Vue.use(Vuex); //调用了 vuex 中的 一个 install() 方法
- 创建 Vuex 实例对象
const Vuex = new Vuex.store({});
- 将 store 对象挂载到 vue 对象上
new Vue({
render: (h) => h("#app"),
store,
});
3. state
state 是放置所有公共状态的属性,如果你有一个公共状态数据 , 你只需要定义在 state 对象中
// 初始化vuex对象
const store = new Vuex.Store({
state: {
// 管理数据
count: 0,
name: "张三",
age: 18,
},
});
调用 state 里的数据的三种方法:
- 方式一: 通过 state 属性属性获取 count
<template>
<p>state的数据:{{ $store.state.count }}</p>
</template>
- 方式二 :state 属性定义在计算属性中,自动将指定数据挂载到 computed 上
<template>
<p>state的数据:{{ count }}</p>
</template>
<script>
export default{
computed: {
count() {
return this.$store.state.count,
},
},
}
</script>
- 方法三:使用辅助函数 - mapState
<template>
<div>state的数据:{{ count }}</div>
<div>state的数据:{{ name }}</div>
<div>state的数据:{{ age }}</div>
</template>
<script>
//1.引入 mapState 函数
import { mapState } from "vuex";
export default{
computed: {
// 2利用延展运算符将导出的状态映射给计算属性
...mapState(["count", "name", "age"]),
},
}
</script>
4. mutations
mutations 是一个对象,对象中存放修改 state 的方法
定义mutations
// 初始化vuex对象
const store = new Vuex.Store({
state: {
// 管理数据
count: 0,
name: "张三",
age: 18,
},
mutations: {
//参数一:必须是 state ,不用手动传
//参数二:调用时传入的参数payload(载荷)
addCount(state, count) {
state.count += count;
},
},
});
调用 mutations 里的 方法 的两种方法:
- 方式一:原始形式-$store
<template>
<div>
<button @click="addCount">count加+</button>
</div>
</template>
<script>
export default {
// 方法一原始形式-$store
methods: {
addCount() {
// 参数一:方法名 参数二 参数
this.$store.commit("addCount", 10);
},
},
};
</script>
- 方法二:辅助函数 - mapMutations
<template>
<div>
<button @click="addCount(100)">count加100+</button>
</div>
</template>
<script>
import { mapMutations } from "vuex";
export default {
// 方法一原始形式-$store
methods: {
addCount() {
// 参数一:方法名 参数二 参数
...mapMutations(["addCount"]),
},
},
};
</script>
5. actions
什么时候使用 **actions **?
- 当我们需要进行异步操作的时候(比如发送请求),我们就应该创建一个 action 来进行异步操作
- 因为 mutations 不支持异步操作
actions 的使用注意:不能直接修改 state 的数据,必须通过 mutations 方法间接的修改 state 的数据
访问形式有以下两种:
定义actions
// 初始化vuex对象
const store = new Vuex.Store({
state: {
...
},
mutations: {
...
},
actions: {
getAsyncCount(context) {
// cintext 对象-> $store
// action 不能做直接操作
//可以通过 context.state 获取状态 也可以通过context.commit 来提交mutations, 也可以 context.diapatch调用其他的action
setTimeout(() => {
context.commit("addCount", 123);
}, 1000);
},
},
});
- 原始调用 - $store
<template>
<div>
<button @click="addAsyncCount">异步原始调用+100</button>
</div>
</template>
<script>
export default {
methods: {
addAsyncCount() {
//actions 方法一 原始调用 - $store
this.$store.dispatch("getAsyncCount");
},
},
};
</script>
- 辅助函数 -mapActions
<template>
<div>
<button @click="getAsyncCount">异步辅助函数 -mapActions+111</button>
</div>
</template>
<script>
import { mapActions } from "vuex";
export default {
methods: {
addAsyncCount() {
// actions 方法二
...mapActions(["getAsyncCount"]),
},
},
};
</script>
6. getters
在什么时候使用 getters ?
- 当我们有一个 state 中的数据经常需要使用,我们就可以为这个数据建立一个 getters
- 或者我们可以把多个数据整合起来制作成一个 getters ,提供访问
- 再者也可能我们需要得到数据需要进行计算,我们可以创建一个 getters 进行计算,并得到最后的结果
- getters 可以作为提供快速访问数据的一种形式,也可以作为类似计算属性的方式来使用
使用方式有以下两种:
定义 getters
// 初始化vuex对象
const store = new Vuex.Store({
state: {
...
list: [1,2,3,4,5,6,7,8,9,10]
},
mutations: {
...
},
actions: {
...
},
getters:{
// getters函数的第一个参数是 state
// 必须要有返回值
filterList: state => state.list.filter(item => item > 5)
}
});
- 原始形式-$store
<template>
<div>{{ $store.getters.filterList }}</div>
</template>
- 辅助函数 - mapGetters
<template>
<div>
{{ filterList }}
</div>
</template>
<script>
import { mapGetters } from "vuex";
export default {
computed: {
...mapGetters(['filterList'])
}
};
</script>
7.模块化-Module
Vuex为什么要有模块化?
- 所有的数据都放在 state 中,所有修改数据的方法都放在 mutations ,所有的异步操作都放在 actions 里面,会导致 Vuex 的 store 对象非常臃肿,后续做维护,添加新功能都会比较费劲
- 而通过模块化,我们可以将主模块 Vuex 的 store 拆分成多个子模块,功能划分更加清晰,后续维护更新更易查找
8.模块化的简单应用
应用
定义两个模块 user 和 setting
user中管理用户的状态 token
setting中管理 应用的名称 name
// 初始化vuex对象
const store = new Vuex.Store({
state: {...},
mutations: {...},
actions: {...},
getters:{
// ...
token: state => state.user.token,
name: state => state.setting.name,
},
modules: {
user: {
state: {
token: "12345",
},
},
setting: {
state: {
name: "Vuex实例",
},
},
},
});
调用:
- 原始方法
<template>
<div>
<div>用户token {{ $store.state.user.token }}</div>
<div>网站名称 {{ $store.state.setting.name }}</div>
</div>
</template>
- 通过mapGetters引用 访问模块数据
<template>
<div>
<div>用户token {{ token }}</div>
<div>网站名称 {{ name }}</div>
</div>
</template>
<script>
import { mapGetters } from "vuex";
export default {
computed: {
// 通过mapGetters引用 访问模块数据
...mapGetters(["token", "name"]),
}
};
</script>
9. 模块化中的命名空间
默认情况下,模块内部的 action、mutation 和 getter 是注册在全局命名空间的——这样使得多个模块能够对同一 mutation 或 action 作出响应。
// 初始化vuex对象
const store = new Vuex.Store({
state: {...},
mutations: {...},
actions: {...},
getters:{
// ...
token: state => state.user.token,
name: state => state.setting.name,
},
modules: {
user: {
// 想保证内部模块高封闭性,我们可以采用namespaced来进行设置
namespaced: true,
state: {
token: "12345",
},
mutations: {
// 这里的state表示的是user的state
updateToken(state) {
state.token = 678910;
},
},
},
setting: {
state: {
name: "Vuex实例",
},
},
},
});
方案1:直接调用-带上模块的属性名路径
<template>
<div>
<button @click="test">修改token</button>
</div>
</template>
<script>
export default {
methods: {
test () {
this.$store.dispatch('user/updateToken') // 直接调用方法
}
}
};
</script>
方案2:辅助函数-带上模块的属性名路径
<template>
<div>
<button @click="test">修改token</button>
</div>
</template>
<script>
import { mapMutations } from "vuex";
export default {
methods: {
...mapMutations(['user/updateToken']),
test () {
this['user/updateToken']()
}
}
};
</script>
方案3: createNamespacedHelpers 创建基于某个命名空间辅助函数
<template>
<div>
<button @click="updateToken">修改token2</button>
</div>
</template>
<script>
import { mapGetters, createNamespacedHelpers } from 'vuex'
const { mapMutations } = createNamespacedHelpers('user')
export default {
methods: {
// 通过mapMutations调用
...mapMutations(["updateToken"]),
}
};
</script>