Vue组件通信的几种实现方法


Posted in Javascript onApril 25, 2019

组件的通信

Vue组件通信的几种实现方法

一般常见的组件之间的通信有以下几种情况,A和B,B和C,B和D之间都是父子关系,C和D之间是兄弟组件关系。

常用的通信手段有两种:

1.ref:给元素或组件注册引用信息

2.children:访问父级组件和子组件的实例。

这两种方式都是直接通过实例的方式获取的方式。示例如下:

//comA组件A
export default {
 data () {
 return {
  title: '测试通信'
 }
 },
 methods: {
 sayHello () {
  window.alert('你好');
 }
 }
}

这里引用组件A

<template>
 <comA ref="comA"></comA>
</template>
<script>
 export default {
 mounted () {
  const comA = this.$refs.comA;
  console.log(comA.title); // 测试通信
  comA.sayHello(); // 调用组件comA的方法
 }
 }
</script>

上面的例子我们可以看出我们使用ref来获取组件的实例上的方法和数据

<div id="count">
 <button @click="showmsg">
  显示两个组件的信息
 </button>
  <child1></child1>
 <child2></child2>
 </div>
<template id="child1">
 <div>
 {{ msg }}
 </div>
</template>
<template id="child2">
 <div>
 {{ msg }}
 </div>
</template>
<script>
 Vue.component('child1', {
  template: '#child1',
  data () {
  return {
   msg: '这是子组件1的信息'
  }
  }
 })
 Vue.component('child2', {
  template: '#child2',
  data () {
  return {
   msg: '这是子组件2的信息'
  }
  }
 })
 new Vue({
  el: '#count',
  data: {
  
  },
  methods: {
  showmsg () {
   for(var i = 0; i < this.$children.length; i++) {
   alert(this.$children[i].msg)
   }
  }
  }
 })
</script>

$children 返回所有子组件的实例,是一个数组

<div id="count">
 父组件中的msg: {{ msg }}
  <child1 ref='c1'></child1>
 <child2 ref='c2'></child2>
 </div>
<template id="child1">
 <div>
 {{ msg }}
 <button @click="showpmsg">
  显示父组件msg
 </button>
 </div>
</template>
<template id="child2">
 <div>
 {{ msg }}
 </div>
</template>
<script>
 Vue.component('child1', {
  template: '#child1',
  data () {
  return {
   msg: '这是子组件1的信息'
  }
  },
  methods: {
  showpmsg () {
    alert(this.$parent.msg)
  }
  }
 })
 Vue.component('child2', {
  template: '#child2',
  data () {
  return {
   msg: '这是子组件2的信息'
  }
  }
 })
 new Vue({
  el: '#count',
  data: {
  msg: 'hello parent'
  }
 })
</script>

这两种方式是基于组件的上下文环境访问到父组件或者全部子组件(数组)。这种方式有很大的弊端是,无法跨级或兄弟间进行通信,比如如下的结构

// parent.vue
<component-a></component-a>
<component-b></component-b>
<component-c></component-c>

我们假如想在组件A中获取其他组件那么我们可能需要使用vuex或者和Bus事件总线的方式进行解决。

事件总线

定义事件总线的方式有以下两种

// bus.js 事件总线

import Vue from 'vue'
export const $bus = new Vue()
// main.js我们再main入口中定义这个事件总线
Vue.prototype.$bus = new Vue()

发送事件

对下面comA说明,会接收来自父组件的参数number,并显示出来;有个按钮,点击会调用函数handleAddRandom,生成一个随机数,并调用事件总线的$emit方法,将随机数给事件总线,由事件总线进行数据传递。

<template>
 <div>
 {{number}}
 <button @click="handleAddRandom">随机增加</button>
 </div>
</template>

<script>
import $bus from ../bus.js
 export default {
 name: "counter",
 props: {
  number: {
  type: Number
  }
 },
 methods: {
  handleAddRandom() {
  const num = Math.floor(Math.random() * 100 + 1);
  console.log("生产的num:" + num);
  this.$bus.$emit('add', num);
  }
 }
 }
</script>

接收事件

<template>
 <div>
 随机增加:
 <counter :number="number"></counter>
 </div>
</template>

<script>
 import counter from './counter'

 export default {
 name: "index",
 components: {
  counter
 },
 data() {
  return {
  number: 0
  }
 },
 methods: {
  handleAddRandom(num) {
  this.number += num;
  }
 },
 created() {
  //this.$bus.$on需要在created中使用,否则不会生效
  this.$bus.$on('add', this.handleAddRandom);
 },
 beforeDestroy() {
  //需要在beforeDestroy中移除
  this.$bus.$off('add', this.handleAddRandom);
 }
 }
</script>

<style scoped>

</style>

上面是我们通过事件总线的方式进行通信

然后我们来说下另一种可以媲美Vuex的一种方式provide / inject

provide / inject

说起这两个API可能大家不太明白我们来举例子说明

// A组件
export default {
 provide: {
 name: 'Aresn'
 }
}

// B组件
export default {
 inject: ['name'],
 mounted () {
 console.log(this.name); // Aresn
 }
}

代码中我们可以看到我们再组件A中设置了一个provide:{name:"Aresn"},这个方法的作用就是将该变量提供给所有的子组件。我们在B组件中我们使用indect获取了这个变量,这样我们就可以使用this.name获取到这个那么变量。下面我们可以使用一些骚操作大胆的替代Vuex。(这里说明一下官网中不建议我们是使用这两个API在常规应用程序中,建议使用在高阶组件中,建议归建议用的好就可以啦)

使用provide / inject期待Vuex

<template>
 <div>
 <router-view></router-view>
 </div>
</template>
<script>
 export default {

 }
</script>
Vue cli中搭建出来的项目结构中都会有一个app.vue作为入口组件,我们可以使用这个API在上面大做文章。
<script>
 export default {
 provide () {
  return {
  app: this
  }
 },
 data () {
  return {
  userInfo: null
  }
 },
 methods: {
  getUserInfo () {
  // 这里通过 ajax 获取用户信息后,赋值给 this.userInfo,以下为伪代码
  $.ajax('/user/info', (data) => {
   this.userInfo = data;
  });
  }
 },
 mounted () {
  this.getUserInfo();
 }
 }
</script>

这里我们把根组件实例作为一个参数传递给app变量,下面我们就可以通过app[变量||方法]达到vuex的目的

<template>
 <div>
 {{ app.userInfo }}
 </div>
</template>
<script>
 export default {
 inject: ['app'],
 methods: {
  changeUserInfo () {
  // 这里修改完用户数据后,通知 app.vue 更新,以下为伪代码
  $.ajax('/user/update', () => {
   // 直接通过 this.app 就可以调用 app.vue 里的方法
   this.app.getUserInfo();
  })
  }
 }
 }
</script>

但是这样做有一个弊端那就是可能会让根组件app.vue的代码变得特别的臃肿,当然也有解决办法,我们可以使用mixins混合的方式将不同的逻辑分开写到不同的js里面然后通过 mixins: [mixins_user]的方式在app.vue中引用这个mixin。

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

Javascript 相关文章推荐
JQuery Tips(3) 关于$()包装集内元素的改变
Dec 14 Javascript
js移除事件 js绑定事件实例应用
Nov 28 Javascript
js 实现的可折叠留言板(附源码下载)
Jul 01 Javascript
js插件YprogressBar实现漂亮的进度条效果
Apr 20 Javascript
JS动态给对象添加属性和值的实现方法
Oct 21 Javascript
详解AngularJS ng-class样式切换
Jun 27 Javascript
基于jQuery的表单填充实例
Aug 22 jQuery
JavaScript判断输入是否为数字类型的方法总结
Sep 28 Javascript
iview table render集成switch开关的实例
Mar 14 Javascript
详解webpack运行Babel教程
Jun 13 Javascript
webpack proxy 使用(代理的使用)
Jan 10 Javascript
vue实现移动端div拖动效果
Mar 03 Vue.js
深入解析vue 源码目录及构建过程分析
Apr 24 #Javascript
使用webpack4编译并压缩ES6代码的方法示例
Apr 24 #Javascript
页面内锚点定位及跳转方法总结(推荐)
Apr 24 #Javascript
详解Vue项目中实现锚点定位
Apr 24 #Javascript
微信小程序中使用echarts的实现方法
Apr 24 #Javascript
基于mpvue小程序使用echarts画折线图的方法示例
Apr 24 #Javascript
详解微信小程序开发用户授权登陆
Apr 24 #Javascript
You might like
PHP学习笔记之二
2011/01/17 PHP
PHP rawurlencode与urlencode函数的深入分析
2013/06/08 PHP
php实现利用phpexcel导出数据
2013/08/24 PHP
非常有用的9个PHP代码片段
2016/04/06 PHP
PHP+AJAX 投票器功能
2017/11/11 PHP
Aster vs KG BO3 第二场2.19
2021/03/10 DOTA
JS实现浏览器菜单命令
2006/09/05 Javascript
Javascript与vbscript数据共享
2007/01/09 Javascript
JavaScript 学习笔记(十四) 正则表达式
2010/01/22 Javascript
jQuery学习笔记之 Ajax操作篇(一) - 数据加载
2014/06/23 Javascript
jQuery源码解读之removeClass()方法分析
2015/02/20 Javascript
JavaScript实现在标题栏上显示当前日期的方法
2015/03/19 Javascript
使用Sticky组件实现带sticky效果的tab导航和滚动导航的方法
2016/03/22 Javascript
jQuery页面弹出框实现文件上传
2017/02/09 Javascript
Angular组件化管理实现方法分析
2017/03/17 Javascript
Vuex实现数据增加和删除功能
2019/11/11 Javascript
[46:20]TFT vs Secret Supermajor小组赛C组 BO3 第二场 6.3
2018/06/04 DOTA
为python设置socket代理的方法
2015/01/14 Python
Python执行时间的计算方法小结
2017/03/17 Python
python爬虫爬取快手视频多线程下载功能
2018/02/28 Python
python中ASCII码和字符的转换方法
2018/07/09 Python
使用50行Python代码从零开始实现一个AI平衡小游戏
2018/11/21 Python
python修改文件内容的3种方法详解
2019/11/15 Python
Python pandas对excel的操作实现示例
2020/07/21 Python
Python: glob匹配文件的操作
2020/12/11 Python
分享一个页面平滑滚动小技巧(推荐)
2019/10/23 HTML / CSS
利用HTML5 Canvas制作一个简单的打飞机游戏
2015/05/11 HTML / CSS
意大利领先的奢侈品在线时装零售商:MCLABELS
2020/10/13 全球购物
学生发电厂实习自我鉴定
2013/09/22 职场文书
《诚实与信任》教学反思
2014/04/10 职场文书
国际语言毕业生求职信
2014/07/08 职场文书
英语课前三分钟演讲稿
2014/08/19 职场文书
干部考核工作总结2015
2015/07/24 职场文书
婚礼领导致辞大全
2015/07/28 职场文书
2016领导干部廉洁自律心得体会
2016/01/13 职场文书
在HTML5 localStorage中存储对象的示例代码
2021/04/21 Javascript