参考:

详解vuex 解决多个组件之间的通信问题_Allen的博客-CSDN博客

详解vuex
1.安装 yarn add vuex2.引入vuex 并且让vue使用vuex新建文件src/store/index.js(仓库)
//引入vueximport Vuex from "vuex"import Vue from "vue"Vue.use(Vuex)  //让vue使用Vuex//创建store仓库let store = new Vuex.Store({//里面写store相关的配置项})export default store;  //需要暴露出去12345678

3.在main.js入口文件里注册store//引入vuex的实例import store from "./store"new Vue({  render: h => h(App),  router,  //就是为了让每一个组件都可以访问到路由相关的api ($router/$route)  store    //目的就是为了让每一个组件都可以访问到vuex相关的api ($store)}).$mount('#app')12345674.在仓库中index.js 定义 以及更改状态定义isTababrShow 以及 更改isTabbarShow状态的方法
//创建storelet store = new Vuex.Store({    state:{ //就是用来定义多组件之间的共享状态        isTabbarShow:true    },    mutations:{  //如vuex流程图,只要mutations有权限更改state,    //同时这里也提供了很多更改状态的方法        show(state){            state.isTabbarShow = true        },        hide(state){            state.isTabbarShow = false        }    } })1234567891011121314155.在主入口文件App.vue里面对状态进行关联 <Tabbar v-show="$store.state.isTabbarShow"></Tabbar>  16.在Search.vue触发钩子函数一进入search页面不让tabbar显示
created(){    //一进入search,需要更改仓库isTabbarShow将其变成false    this.$store.commit("hide")  },  beforeDestroy(){    //一旦离开search,isTabbarShow true    this.$store.commit("show")  }12345678


同步操作闭环形成
通过vuex异步请求数据

Cinema.vue
toSearch(){this.$router.push("/search")}123发现Search与Cinema组件中的数据都是一致的,不需要进入到每个组件都请求一次数据,可以在vuex中的action里面进行异步请求即可。
1.在仓库中定义以及更改状态store/index.js
state:{ //就是用来定义多组件之间的共享状态  this.$store.state.isTabbarShow        isTabbarShow:true,        cinemaList:[]},
 actions:{        getCinemaListAction(context){            instance.get("/gateway?cityId=310100&ticketFlag=1&k=2654330",{                headers:{                  'X-Host': 'mall.film-ticket.cinema.list'                }              }).then(res=>{              // 如何更改vuex中的cinemaList这个状态?                 // 需要触发mutations的setCinemaList这个方法                 // 第一个参数就是触发的具体的mutations的名称  第二个参数就是给其传入的异步请求获取到的数据                context.commit("setCinemaList",res.data.data.cinemas)            })        }    },  mutations:{ //后续唯一可以更改state的地方        show(state){  //组件中如何调用此方法?  this.$store.commit("方法名")            state.isTabbarShow = true        },        hide(state){            state.isTabbarShow = false        },        setCinemaList(state,cinemaList){         //第二个参数可以接受外面传递过来的参数            state.cinemaList = cinemaList        }    }})12345678910111213141516171819202122232425262728293031322.在Cinema组件中进行触发action的方法:created(){    //需要调用dispatch触发vuex的action方法    this.$store.dispatch("getCinemaListAction")  }1234需要在Cinema中使用vuex的状态cinemaList
  cinemaArea(){  let newArr = this.$store.state.cinemaList.map(item=>{    return item.districtName  })  return ["全城",...new Set(newArr)]},filterCinemaArea(){  if(this.currentArea === "全城") return this.$store.state.cinemaList;  return this.$store.state.cinemaList.filter(item=>{    return item.districtName === this.currentArea ? true : false  })}123456789101112回到Search页面,发现vuex的全局状态管理的优势体现出来了。多组件数据共享
3.vuex存储是内存,一刷新就没有了,如果不刷新界面,可以实现多组件的数据共享。因为vuex中的数据存内存中的,一刷新就会恢复初始值。Search.vue
created(){    if(this.$store.state.cinemaList.length>0){   console.log("vuex中的cinemaList数据有了...")    }else{ //刷新了 vuex中没有数据      this.$store.dispatch("getCinemaListAction")    }    this.$store.commit("hide")  },12345678vuex的getters获取5条影院数据开始是在Search.vue里
getCinemaListFive(){ //组件的computed依赖于data数据return this.$store.state.cinemaList.slice(0,5)},123如果在别的地方,也需要用到vuex的5条数据的话,也得需要写一次上述的计算属性。
需要在store/index.js里面的getters去进行单独的定义了。
getters:{  //类似于computed计算属性 只不过里面的数据依赖于vuex的状态        getCinemaListFive(state){            return state.cinemaList.slice(0,5)        }, },12345之后在Search.vue里去调用
<li    v-for="data in $store.getters.getCinemaListFive"    :key="data.cinemaId">{{data.name}}</li>1234vuex辅助函数(mapState,mapGetters,mapActions,mapMutations)
mapStatemapState这个辅助函数就是为了方便获取vuex中的状态,本来获取状态 this.$store.state.xxx
import { mapState } from 'vuex'
computed:{    ...mapState(["cinemaList"]),      cinemaArea(){      //获取vuex的状态,直接通过this既可以访问到了      let newArr = this.cinemaList.map(item=>{        return item.districtName      })       return ["全城",...new Set(newArr)]},filterCinemaArea(){  if(this.currentArea === "全城") return this.cinemaList  return this.cinemaList.filter(item=>{    return item.districtName === this.currentArea ? true : false  })}}12345678910111213141516171819后续如果你的computed中有跟vuex的同名的,需要通过这种方式设置
...mapState({     aaa:state=>state.cinemaList }),123mapGetters这个辅助函数与mapState的用法一模一样
import {mapState,mapGetters} from "vuex"1computed:{    ...mapState(["cinemaList"]),    ...mapGetters(["getCinemaListFive"]),}1234 v-for="data in getCinemaListFive"    //$store.getters.getCinemaListFive1modules因为store是单一的数据源,项目中创建的store的实例只能是一个,所以数据全都放在这一个大的实例对象中,很难去维护,所以需要对于store进行模块划分。
store/module/tabbar.js
const tabbar = {    namespaced: true,    state:{        isTabbarShow:true,    },    mutations:{        show(state){  //组件中如何调用此方法?  this.$store.commit("方法名")            state.isTabbarShow = true        },        hide(state){            state.isTabbarShow = false        }    }}
export default tabbar;12345678910111213141516store/module/cinema.js
import {instance} from "@/utils/http"const cinema = {    namespaced: true,    state:{        cinemaList:[]    },    getters:{        getCinemaListFive(state){            return state.cinemaList.slice(0,5)        },    },    actions:{        getCinemaListAction(context){            instance.get("/gateway?cityId=310100&ticketFlag=1&k=2654330",{                headers:{                  'X-Host': 'mall.film-ticket.cinema.list'                }              }).then(res=>{                // 需要触发mutations的setCinemaList这个方法                 // 第一个参数就是触发的具体的mutations的名称  第二个参数就是给其传入的异步请求获取到的数据                context.commit("setCinemaList",res.data.data.cinemas)            })        }    },    mutations:{        setCinemaList(state,cinemaList){            state.cinemaList = cinemaList        }    }}
export default cinema;1234567891011121314151617181920212223242526272829303132store/index.js
import tabbar from "./module/tabbar"import cinema from "./module/cinema"
//创建storelet store = new Vuex.Store({    modules: { //通过modules将所有的分支的模块进行合并        tabbar,        cinema    }})
1234567891011Cinema.vue
...mapState("cinema",["cinemaList"]),    //前提一定需要在module模块里面声明namespace:true1派发方法,也得需要按照指定的模块名字请求action与mutations
this.$store.dispatch("cinema/getCinemaListAction")1Search.vue
...mapState("cinema",["cinemaList"]),...mapGetters("cinema",["getCinemaListFive"]),12created(){    if(this.cinemaList.length>0){    }else{       //dispatch("module名字/action方法")      this.$store.dispatch("cinema/getCinemaListAction")    }        //commit("module名字/commit方法")    this.$store.commit("tabbar/hide")  },  beforeDestroy(){    //commit("module名字/commit方法")    this.$store.commit("tabbar/show")  }1234567891011121314App.vue
import {mapState} from "vuex"
computed:mapState("tabbar",["isTabbarShow"])123<Tabbar v-show="isTabbarShow"></Tabbar>  1Search
<button @click="back">取消</button>methods:{    back(){      this.$router.back()    }},123456mapActions这个辅助函数用法与上面一致,但是需要定义在methods里面
import { mapState,mapActions } from 'vuex'1methods:{    ...mapActions("cinema",["getCinemaListAction"]),}123created(){    if(this.cinemaList.length === 0){      // this.$store.dispatch("cinema/getCinemaListAction")      this.getCinemaListAction()    }  }123456mapMutations这个辅助函数用法与上面一致的用法
import {mapState,mapGetters,mapMutations,mapActions} from "vuex"1methods:{    ...mapActions("cinema",["getCinemaListAction"]),    ...mapMutations("tabbar",["show","hide"]),}1234created(){    if(this.cinemaList.length>0){
    }else{ //刷新了 vuex中没有数据      this.getCinemaListAction()    }    this.hide()},beforeDestroy(){    this.show()}
123456789101112vuex 项目结构Vuex 并不限制你的代码结构。但是,它规定了一些需要遵守的规则:
应用层级的状态应该集中到单个 store 对象中。提交 mutation 是更改状态的唯一方法,并且这个过程是同步的。异步逻辑都应该封装到 action 里面。只要你遵守以上规则,如何组织代码随你便。如果你的 store 文件太大,只需将 action、mutation 和 getter 分割到单独的文件。————————————————版权声明:本文为CSDN博主「Allen 赵奇隆」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。原文链接:https://blog.csdn.net/zqlbanzhuan/article/details/109045145