父与子之间的通信比较简单,相信你可以通过自定义属性和自定义事件解决,emmmm......相信简单的兄弟之间的通信你也可以通过全局事件总线$bus解决。
但是,当组件比较多,需要通信的组件间关系比较复杂时,数据的流动很不清晰,并且数据管理起来也比较复杂。
放心,总有办法解决,这不,救星来了——vuex
vuex的优点有很多,它就像是仓库一样,存储着组件之间需要共享的数据,简直就是行走的“数据管理员”,最重要的是它还是与时俱进的,存储的数据都是响应式的。
1.vuex的五个家庭成员
vuex是由state、mutations、getters、actions、modules五个成员组成的“大家庭”。他们各自扮演着不同的角色,辛勤付出...
五个之间的关系及与组件的关系
他们五个之间的关系以及与外界组件之间的关系,我先用一张图表示出来。
组件得到接口数据流程
主要的流程:
- 组件通知actions获取接口数据
- actions将得到的数据传给mutations
- mutations相当于methods,能够将数据处理后,放入state中,只有它能够改变state中的数据
- 当然,当state中的数据比较复杂的时候,就可以使用getters(相当于计算属性)将数据简化
- 组件能够直接使用state中的数据,也可以使用getters中简化了的数据,同样也能够通知mutations修改state中的值
注:大仓库可以分为小仓库,小仓库中的基本结构与大仓库相同,小仓库放入大仓库中的modules中
五个成员的具体总结
所以,说了这么多,来对这五个成员进行一个总结。
-
state:存放公共数据(类似于data)
-
mutations :使用它来修改数据,同步函数,不能进行异步操作
-
getters: 类似于计算属性,对现有的状态进行计算得到新的数据,可以简化state中的数据
-
actions: 书写自己的业务逻辑,发起异步请求
-
modules: 模块拆分
什么情况下拆分模块
当项目中的组件很多,需共享的数据很多,如果都放入同一个大仓库中,那么使vuex的结构比较混乱,维护起来就没有这么容易,故这时就拆分模块,每个模块存放对应的数据,将这一个个小的仓库放入大仓库中。
2.vuex在项目中的配置(没有拆分模块)
一般在项目中创建一个store的包,存放与vuex相关。
在store/index.js中放置具体的代码,如下:
import Vue from 'vue'
import vuex from 'vuex'
// 注册vuex
Vue.use(vuex)
const state={}
const mutations={}
const getters={}
const actions={}
const modules={}
// 默认导出vuex中的Store
export default new vuex.Store({
state,
mutations,
getters,
actions,
modules //如果要拆分模块的话,也很简单,放入此处中就可以
})
向vue的实例中注入store——在src/main.js中导入store,并注入vue实例中,代码如下:
// 省略其他
// 导入vuex
import store from './store/index'
new Vue({
render: h => h(App),
// 省略其他
store
}).$mount('#app')
3.组件调用或访问vuex中的成员
3.1组件访问state中的数据
- 直接通过
this.$store.state.要访问的全局数据名称访问state中的数据 - 通过vuex提供的mapState辅助函数,把store中的数据映射到组件中的computed中,示例代码如下:
import {mapState} from 'vuex'
export default{
computed:{
// 这里可以是数组形式,也可以是对象形式
// 当进行模块拆分了的,就可以使用对象形式
...mapState(['count'])
}
}
3.2组件访问getters
- 直接通过
this.$store.getters.getters的名称 - 通过vuex提供的mapGetters辅助函数,同样给映射到组件中的computed中,示例代码如下:
import {mapGetters} from 'vuex'
export default{
computed:{
...mapGetters(['count'])
}
}
3.3组件调用mutations
- 直接通过
this.$store.commit('mutations名称',载荷)来调用 - 通过vuex提供的mapMutations辅助函数,映射到组件中的methods中,示例代码如下:
import {mapMutations} from 'vuex'
export default{
methods:{
...mapMutations(['sub'])
}
}
3.4组件调用actions
- 直接通过
this.$store.dispatch('actions的名字',参数)来调用 - 通过vuex提供的mapActions辅助函数,映射到组件中的methods中,示例代码如下:
import {mapActions} from 'vuex'
export default{
methods:{
...mapActions(['actions名'])
// ...mapActions({'新名字': 'actions名'})
}
}
4.拆分模块
拆分后store包的结构
store/index.js中的配置代码如下:
import Vue from 'vue'
import vuex from 'vuex'
// 注册vuex
Vue.use(vuex)
// 导入模块化的vuex
import Home from './Home/index'
import Search from './Search/index'
// 默认导出vuex中的Store
export default new vuex.Store({
// 存放模块化的vuex数据
modules: {
Home,
Search
}
})
跟没有拆分模块一样,都需要将store注入到vue实例中。
其中Search里面主要是存放搜索的相关数据,这里面的代码就是按照组件获取接口数据流程来的, store/Search/index.js中示例代码如下:
// 存放search中的数据
// 导入访问接口的函数
import { reqSearch } from "@/api"
const state = {
// 获取搜索商品 注意:这个类型为object是根据前面传过来的数据的类型决定的,不是随意写的
getSearchList:{}
}
const mutations = {
GETSEARCH(state, getdata) {
state.getSearchList=getdata
}
}
// 计算属性,将数据简化出来
const getters = {
// 这里的state就是search中的
goodsList(state) {
return state.getSearchList.goodsList
}
}
const actions = {
async getSearch({commit},params={}) {
// 从接口中获取的数据为Promise
let result = await reqSearch(params)
if (result.code == 200) {
// 将数据提交给commit
commit('GETSEARCH',result.data)
}
}
}
export default({
state,
mutations,
getters,
actions
})
外面的组件可以获取里面的getters、state数据。
// import { mapState } from 'vuex'
import { mapGetters } from 'vuex'
export default{
name:'Search',
// 当挂载完毕,就通知vuex中的actions获取接口中的数据
// 注意,因为这是异步操作,所以只能通过actions
mounted(){
this.$store.dispatch('getSearch', '参数')
},
computed: {
// 就是因为这样获取state中的数据比较麻烦,就体现了getters的好处
// ...mapState({
// getdata: (state) => {
// return state.Search.getSearchList.goodsList
// }
// })
...mapGetters(['goodsList'])
}
}
结语:vuex集中式的管理项目中组件的数据,方便了组件之间的数据通信,说起组件的通信,是十分重要的!!!下篇就写写组件之间的通信吧。