转载

vue跨组件通信的几种方法

在开发组件的时候,一定会遇到组件的通信,比如点击一个图标出现弹窗和蒙层,这三个分别是不同的组件。管理他们之间的状态就成了问题。

props双向绑定

官方文档在这 ,通过 sync 双向绑定,属性变化会同步到所有组件,这也是最简单的实现方式,缺点是属性会比较多。实现方式如下

App.vue 文件

<template>   <div id="app">     <mask :hide-mask.sync="hideMask"></mask>     <dialog :hide-dialog.sync="hideDialog" :hide-mask.sync="hideMask"></dialog>     <dialog-icon :hide-dialog.sync="hideDialog" :hide-mask.sync="hideMask"></dialog-icon>   </div> </template>  <script> import mask from './components/mask/index' import dialog from './components/dialog/index' import dialogIcon from './components/dialog-icon/index'  export default {   components: {     mask,     dialog,     dialogIcon   },   data () {     return {       hideMask: true,       hideDialog: true     }   } } </script>

component/dialog/index.vue 文件

<template>   <section class="dialog" :class="{ 'hide': hideDialog }">     <div class="dialog-close" @click="hide()"></div>   </section> </template>  <script> export default {   props: ['hideDialog', 'hideMask'],   methods: {     hide () {       this.hideDialog = !this.hideDialog       this.hideMask = !this.hideMask     }   } } </script>

component/dialog-icon/index.vue 文件

<template>   <section class="dialog-icon" @click="show()">点击出现弹窗</section> </template>  <script> export default {   props: ['hideDialog', 'hideMask'],   methods: {     show () {       this.hideDialog = !this.hideDialog       this.hideMask = !this.hideMask     }   } } </script>

component/mask/index.vue 文件

<template>   <div class="mask" :class="{ 'hide': hideMask }"></div> </template>  <script> export default {   props: ['hideMask'] } </script>

自定义事件

官方文档在这 ,子组件 $dispatch() 派发事件传递给父组件,父组件 $broadcast() 广播事件传递给子组件,这种方式虽然减少了props的使用,但是需要额外定义几个事件,状态多了就会变得很复杂,实现方法如下

App.vue 文件

<template>   <div id="app">     <mask></mask>     <dialog></dialog>     <dialog-icon></dialog-icon> </template>  <script> import mask from './components/mask/index' import dialog from './components/dialog/index' import dialogIcon from './components/dialog-icon/index'  export default {   components: {     mask,     dialog,     dialogIcon   },   data () {     return {       hideMask: true,       hideDialog: true     }   },   events: {     'dialog-dispatch' () {       this.hidedialog = !this.hidedialog       this.$broadcast('dialog-broadcast')     },     'mask-dispatch' () {       this.hideMask = !this.hideMask       this.$broadcast('mask-broadcast')     }   } } </script>

component/dialog-icon/index.vue 文件

<template>   <section class="dialog-icon" @click="show()">点击出现弹窗</section> </template>  <script> export default {   methods: {     show () {       this.$dispatch('dialog-dispatch')       this.$dispatch('mask-dispatch')     }   },   events: {     'dialog-broadcast' () {       this.hideDialog = !this.hideDialog     }   },   data () {     return {       hideDialog: this.$parent.hideDialog,       hideMask: this.$parent.hideMask     }   } } </script>

component/dialog/index.vue 文件

<template>   <section class="dialog" :class="{ 'hide': hideDialog }">     <div class="dialog-close" @click="hide()"></div>   </section> </template>  <script> export default {   methods: {     hide () {       this.$dispatch('dialog-dispatch')       this.$dispatch('mask-dispatch')     }   },   events: {     'dialog-broadcast' () {       this.hideDialog = !this.hideDialog     }   },   data () {     return {       hideDialog: this.$parent.hideDialog,       hideMask: this.$parent.hideMask     }   } } </script>

component/mask/index.vue 文件

<template>   <div class="mask" :class="{ 'hide': hideMask }"></div> </template>  <script> export default {   data () {     return {       hideMask: this.$parent.hideMask     }   },   events: {     'mask-broadcast' () {       this.hideMask = !this.hideMask     }   } } </script>

Vuex

官方文档在这里 ,状态统一放store管理,修改状态通过mutations,组件通过action调用mutations,虽然有点绕,但是所有东西放一起后期会更好维护,实现方法如下

App.vue 文件

<template>   <div id="app">     <mask></mask>     <dialog></dialog>     <dialog-icon></dialog-icon>   </div> </template>  <script> import mask from './components/mask/index' import dialog from './components/dialog/index' import dialogIcon from './components/dialog-icon/index'  export default {   components: {     mask,     dialog,     dialogIcon   } } </script>

component/dialog/index.vue 文件

<template>   <section class="storehouse dialog" :class="{ 'hide': isHideDialog }">     <div class="dialog-close" @click="hideDialog()"></div>   </section> </template>  <script> import { hideDialog } from '../../vuex/actions'  export default {   vuex: {     state: {       isHideDialog: state => state.isHideDialog     },     actions: {       hideDialog     }   } } </script>

component/dialog-icon/index.vue 文件

<template>   <section class="storehouse-icon" @click="hideDialog()">点击出现弹窗</section> </template>  <script> import { hideDialog } from '../../vuex/actions'  export default {   vuex: {     actions: {       hideDialog     }   } } </script>

component/mask/index.vue 文件

<template>   <div class="mask" :class="{ 'hide': isHideMask }"></div> </template>  <script> export default {   vuex: {     state: {       isHideMask: state => state.isHideMask     }   } } </script>

vuex/store.js 文件

import Vue from 'vue' import Vuex from 'vuex' import mutations from './mutations'  Vue.use(Vuex)  const state = {   isHideMask: true,   isHideDialog: true }  const store = new Vuex.Store({   state,   mutations })  if (module.hot) {   module.hot.accept(['./mutations'], () => {     const mutations = require('./mutations').default     store.hotUpdate({       mutations     })   }) }  export default store

vuex/mutations.js 文件

import {   HIDEDIALOG } from './mutation-types'  export default {   [HIDEDIALOG] (state) {     state.isHideDialog = !state.isHideDialog     state.isHideMask = !state.isHideMask   } }

vuex/mutations-types.js 文件

export const HIDEDIALOG = 'HIDEDIALOG'

vuex/action.js 文件

import { HIDEDIALOG } from './mutation-types'  export const hideDialog = ({ dispatch }) => dispatch(HIDEDIALOG)
原文  https://github.com/zhouwenbin/blog/issues/20
正文到此结束
Loading...