始于vue,钟于vuex

51 阅读2分钟

父与子之间的通信比较简单,相信你可以通过自定义属性和自定义事件解决,emmmm......相信简单的兄弟之间的通信你也可以通过全局事件总线$bus解决。

但是,当组件比较多,需要通信的组件间关系比较复杂时,数据的流动很不清晰,并且数据管理起来也比较复杂。

放心,总有办法解决,这不,救星来了——vuex

vuex的优点有很多,它就像是仓库一样,存储着组件之间需要共享的数据,简直就是行走的“数据管理员”,最重要的是它还是与时俱进的,存储的数据都是响应式的。

1.vuex的五个家庭成员

vuex是由statemutationsgettersactionsmodules五个成员组成的“大家庭”。他们各自扮演着不同的角色,辛勤付出...

五个之间的关系及与组件的关系

他们五个之间的关系以及与外界组件之间的关系,我先用一张图表示出来。

image.png

组件得到接口数据流程

主要的流程:

  1. 组件通知actions获取接口数据
  2. actions将得到的数据传给mutations
  3. mutations相当于methods,能够将数据处理后,放入state中,只有它能够改变state中的数据
  4. 当然,当state中的数据比较复杂的时候,就可以使用getters(相当于计算属性)将数据简化
  5. 组件能够直接使用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中的数据

  1. 直接通过this.$store.state.要访问的全局数据名称访问state中的数据
  2. 通过vuex提供的mapState辅助函数,把store中的数据映射到组件中的computed中,示例代码如下:
 import {mapState} from 'vuex'
 
 export default{
     computed:{
     // 这里可以是数组形式,也可以是对象形式
     // 当进行模块拆分了的,就可以使用对象形式
     ...mapState(['count'])
     }
 }

3.2组件访问getters

  1. 直接通过this.$store.getters.getters的名称
  2. 通过vuex提供的mapGetters辅助函数,同样给映射到组件中的computed中,示例代码如下:
 import {mapGetters} from 'vuex'
 
 export default{
     computed:{
     ...mapGetters(['count'])
     }
 }

3.3组件调用mutations

  1. 直接通过this.$store.commit('mutations名称',载荷)来调用
  2. 通过vuex提供的mapMutations辅助函数,映射到组件中的methods中,示例代码如下:
  import {mapMutations} from 'vuex'
  
  export default{
     methods:{
       ...mapMutations(['sub'])
     }
  }

3.4组件调用actions

  1. 直接通过this.$store.dispatch('actions的名字',参数)来调用
  2. 通过vuex提供的mapActions辅助函数,映射到组件中的methods中,示例代码如下:
  import {mapActions} from 'vuex'
  
  export default{
     methods:{
       ...mapActions(['actions名'])
       // ...mapActions({'新名字': 'actions名'})
     }
  }

4.拆分模块

拆分后store包的结构

image.png

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集中式的管理项目中组件的数据,方便了组件之间的数据通信,说起组件的通信,是十分重要的!!!下篇就写写组件之间的通信吧。