详解vue跨组件通信的几种方法


Posted in Javascript onJune 15, 2017

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

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)

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
wordpress之js库集合研究介绍
Aug 17 Javascript
asp.net和asp下ACCESS的参数化查询
Jun 11 Javascript
js 编码转换 gb2312 和 utf8 互转的2种方法
Aug 07 Javascript
jquery用get实现ajax在ie里面刷新不进入后台解决方法
Aug 12 Javascript
再谈Javascript中的基本类型和引用类型(推荐)
Jul 01 Javascript
javascript实现简单的on事件绑定
Aug 23 Javascript
jQuery元素属性操作实例(设置、获取及删除元素属性)
Sep 08 Javascript
利用python分析access日志的方法
Oct 26 Javascript
JS实现的简单图片切换功能示例【测试可用】
Feb 14 Javascript
初学vue出现空格警告的原因及其解决方案
Oct 31 Javascript
JS数组进阶示例【数组的几种函数用法】
Jan 16 Javascript
利用JS判断元素是否为数组的方法示例
Jan 08 Javascript
Bootstrap响应式导航由768px变成992px的实现代码
Jun 15 #Javascript
javascript完美实现给定日期返回上月日期的方法
Jun 15 #Javascript
JS自动生成动态HTML验证码页面
Jun 14 #Javascript
自定义vue全局组件use使用、vuex的使用详解
Jun 14 #Javascript
详解AngularJS 模块化
Jun 14 #Javascript
JS判断时间段的实现代码
Jun 14 #Javascript
bootstrap选项卡扩展功能详解
Jun 14 #Javascript
You might like
谈一谈收音机的高放电路
2021/03/02 无线电
THINKPHP2.0到3.0有哪些改进之处
2015/01/04 PHP
Smarty分页实现方法完整实例
2016/05/11 PHP
PHP实现微信JS-SDK接口选择相册及拍照并上传的方法
2016/12/05 PHP
Laravel 框架基于自带的用户系统实现登录注册及错误处理功能分析
2020/04/14 PHP
form中限制文本字节数js代码
2007/06/10 Javascript
Jquery实现无刷新DropDownList联动实现代码
2010/03/08 Javascript
document.createElement()用法及注意事项(ff下不兼容)
2013/03/13 Javascript
javascript中的=等号个数问题两个跟三个有什么区别
2013/10/23 Javascript
使用JavaScript的AngularJS库编写hello world的方法
2015/06/23 Javascript
this,this,再次讨论javascript中的this,超全面(经典)
2016/01/05 Javascript
js获取地址栏中传递的参数(两种方法)
2017/02/08 Javascript
JS数组操作中的经典算法实例讲解
2017/07/26 Javascript
node基于puppeteer模拟登录抓取页面的实现
2018/05/09 Javascript
JS常见构造模式实例对比分析
2018/08/27 Javascript
在layui中select更改后生效的方法
2019/09/05 Javascript
Vue-cli3生成的Vue项目加载Mxgraph方法示例
2020/05/31 Javascript
Vue结合路由配置递归实现菜单栏功能
2020/06/16 Javascript
js实现特别简单的钟表效果
2020/09/14 Javascript
[55:23]VGJ.T vs Winstrike 2018国际邀请赛小组赛BO2 第二场 8.17
2018/08/20 DOTA
python实现监控windows服务并自动启动服务示例
2014/04/17 Python
mac系统安装Python3初体验
2018/01/02 Python
Python小白必备的8个最常用的内置函数(推荐)
2019/04/03 Python
pytorch 使用单个GPU与多个GPU进行训练与测试的方法
2019/08/19 Python
Django和Flask框架优缺点对比
2019/10/24 Python
使用python matplotlib 画图导入到word中如何保证分辨率
2020/04/16 Python
浅谈Python 命令行参数argparse写入图片路径操作
2020/07/12 Python
pip已经安装好第三方库但pycharm中import时还是标红的解决方案
2020/10/09 Python
css3实现垂直下拉动画菜单示例
2014/04/22 HTML / CSS
幼儿园庆六一活动方案
2014/03/06 职场文书
数学教研活动总结
2014/07/02 职场文书
自查自纠工作总结
2014/10/15 职场文书
那些美到让人窒息的诗句,值得你收藏!
2019/08/20 职场文书
读《儒林外史》有感:少一些功利,多一些真诚
2020/01/19 职场文书
Unicode中的CJK(中日韩统一表意文字)字符小结
2021/12/06 HTML / CSS
Linux下使用C语言代码搭建一个简单的HTTP服务器
2022/04/13 Servers