详解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 相关文章推荐
Prototype使用指南之ajax
Jan 10 Javascript
WordPress 照片lightbox效果的运用几点
Jun 22 Javascript
写js时遇到的一些小问题
Dec 06 Javascript
THREE.JS入门教程(1)THREE.JS使用前了解
Jan 24 Javascript
简单实现js页面切换功能
Jan 10 Javascript
原生js实现键盘控制div移动且解决停顿问题
Dec 05 Javascript
js 将canvas生成图片保存,或直接保存一张图片的实现方法
Jan 02 Javascript
使用vue-cli打包过程中的步骤以及问题的解决
May 08 Javascript
vue之父子组件间通信实例讲解(props、$ref、$emit)
May 22 Javascript
如何检查一个对象是否为空
Apr 11 Javascript
Vue项目中数据的深度监听或对象属性的监听实例
Jul 17 Javascript
JavaScript实现页面高亮操作提示和蒙板
Jan 04 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
discuz安全提问算法
2007/06/06 PHP
php将会员数据导入到ucenter的代码
2010/07/18 PHP
深入分析php中接口与抽象类的区别
2013/06/08 PHP
解析PHP中VC6 X86和VC9 X86的区别及 Non Thread Safe的意思
2013/06/28 PHP
php使用Jpgraph绘制3D饼状图的方法
2015/06/10 PHP
php实现点击可刷新验证码
2015/11/07 PHP
PHP使用Redis长连接的方法详解
2018/02/12 PHP
php curl优化下载微信头像的方法总结
2018/09/07 PHP
数理公式,也可以这么唯美
2021/03/10 无线电
关于 byval 与 byref 的区别分析总结
2007/10/08 Javascript
JQuery 表单中textarea字数限制实现代码
2009/12/07 Javascript
Javascript 网页水印(非图片水印)实现代码
2010/03/01 Javascript
php上传图片并给图片打上透明水印的代码
2010/06/07 Javascript
关于跨站脚本攻击问题
2011/12/22 Javascript
js动态给table添加/删除tr的方法
2013/08/02 Javascript
javascript中文本框中输入法切换的问题
2013/12/10 Javascript
动态添加删除表格行的js实现代码
2014/02/28 Javascript
简单谈谈Javascript中类型的判断
2015/10/19 Javascript
怎么限制input的text里输入的值只能是数字(正则、js)
2016/05/16 Javascript
js 性能优化之算法和流程控制
2017/02/15 Javascript
用JS编写一个函数,返回数组中重复出现过的元素(实例)
2017/09/14 Javascript
mint-ui 时间插件使用及获取选择值的方法
2018/02/09 Javascript
vue实现短信验证码输入框
2020/04/17 Javascript
测试、预发布后用python检测网页是否有日常链接
2014/06/03 Python
Python Web框架Flask中使用新浪SAE云存储实例
2015/02/08 Python
python snownlp情感分析简易demo(分享)
2017/06/04 Python
python读取与写入csv格式文件的示例代码
2017/12/16 Python
Python中常用的8种字符串操作方法
2019/05/06 Python
PyQT5 QTableView显示绑定数据的实例详解
2019/06/25 Python
Keras 在fit_generator训练方式中加入图像random_crop操作
2020/07/03 Python
如何在python中处理配置文件代码实例
2020/09/27 Python
Nike英国官网:Nike.com (UK)
2017/02/13 全球购物
文员个人的求职信范文
2013/09/26 职场文书
教育教学读书笔记
2015/07/02 职场文书
查看nginx配置文件路径和资源文件路径的方法
2021/03/31 Servers
纯 CSS 自定义多行省略的问题(从原理到实现)
2021/11/11 HTML / CSS