详解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 相关文章推荐
使用TextRange获取输入框中光标的位
Oct 14 Javascript
js改变img标签的src属性在IE下没反应的解决方法
Jul 23 Javascript
基于javascript实现浏览器滚动条快到底部时自动加载数据
Nov 30 Javascript
Bootstrap树形菜单插件TreeView.js使用方法详解
Nov 01 Javascript
JS仿京东移动端手指拨动切换轮播图效果
Apr 10 Javascript
微信小程序实现多宫格抽奖活动
Apr 15 Javascript
详解swipe使用及竖屏页面滚动方法
Jun 28 Javascript
js实现倒计时秒杀效果
Mar 25 Javascript
js cavans实现静态滚动弹幕
May 21 Javascript
VueQuillEditor富文本上传图片(非base64)
Jun 03 Javascript
基于javascript的无缝滚动动画实现2
Aug 07 Javascript
Vue过滤器(filter)实现及应用场景详解
Jun 15 Vue.js
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
PHP图片上传代码
2013/11/04 PHP
javascript 设置文本框中焦点的位置
2009/11/20 Javascript
关于js拖拽上传 [一个拖拽上传修改头像的流程]
2011/07/13 Javascript
html中的input标签的checked属性jquery判断代码
2012/09/19 Javascript
javascript确认框的三种使用方法
2013/12/17 Javascript
JavaScript定义类的几种方式总结
2014/01/06 Javascript
FF IE浏览器修改标签透明度的方法
2014/01/27 Javascript
js实现按一下删除键删除整个单词附demo
2014/09/05 Javascript
jQuery实现默认是闭合的FAQ展开效果菜单
2015/09/14 Javascript
jQuery EasyUI 布局之动态添加tabs标签页
2015/11/18 Javascript
详解Bootstrap glyphicons字体图标
2016/01/04 Javascript
Javascript发送AJAX请求实例代码
2016/08/21 Javascript
Bootstrap 3.x打印预览背景色与文字显示异常的解决
2016/11/06 Javascript
JavaScript日期选择功能示例
2017/01/16 Javascript
全面解析Node.js 8 重要功能和修复
2017/06/02 Javascript
浅谈js中的bind
2019/03/18 Javascript
微信小程序利用button控制条件标签的变量问题
2020/03/15 Javascript
jquery css实现流程进度条
2020/03/26 jQuery
python实现ip查询示例
2014/03/26 Python
Python实现的生成自我描述脚本分享(很有意思的程序)
2014/07/18 Python
在Linux系统上安装Python的Scrapy框架的教程
2015/06/11 Python
Python使用Redis实现作业调度系统(超简单)
2016/03/22 Python
PyQt5实现简单数据标注工具
2019/03/18 Python
Python正则表达式匹配数字和小数的方法
2019/07/03 Python
tesserocr与pytesseract模块的使用方法解析
2019/08/30 Python
Python大数据之从网页上爬取数据的方法详解
2019/11/16 Python
Python切割图片成九宫格的示例代码
2020/03/10 Python
PyQt5实现仿QQ贴边隐藏功能的实例代码
2020/05/24 Python
日本无添加化妆品:HABA
2016/08/18 全球购物
EJB包括(SessionBean,EntityBean)说出他们的生命周期,及如何管理事务的
2015/07/24 面试题
机械专业应届生求职信
2013/09/21 职场文书
党建目标管理责任书
2014/07/25 职场文书
校友回访母校寄语
2015/02/26 职场文书
求职信内容一般写什么?
2015/03/20 职场文书
考研导师推荐信范文
2015/03/27 职场文书
一文搞懂php的垃圾回收机制
2021/06/18 PHP