详解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)

以上是 详解vue跨组件通信的几种方法 的全部内容, 来源链接: utcz.com/z/319690.html

回到顶部