vue跨组件通信的几种方法
zhouwenbin opened this issue · 8 comments
在开发组件的时候,一定会遇到组件的通信,比如点击一个图标出现弹窗和蒙层,这三个分别是不同的组件。管理他们之间的状态就成了问题。
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)
正好学习的时候看到,言简意赅,非常感谢~
mark
🐶 🐶 🐶 🐶 🐶
mark
我用你的vuex,报错,我也不知道为什么
@15831929073 文章是1.0版本的
66666
mark