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 相关文章推荐
JavaScript中的事件处理
Jan 16 Javascript
javascript组合使用构造函数模式和原型模式实例
Jun 04 Javascript
JavaScript判断用户名和密码不能为空的实现代码
May 16 Javascript
js实现表单及时验证功能 用户信息立即验证
Sep 13 Javascript
form表单转Json提交的方法(推荐)
Sep 23 Javascript
JS动态生成年份和月份实例代码
Feb 04 Javascript
AngularJS实现自定义指令及指令配置项的方法
Nov 20 Javascript
Angular Renderer (渲染器)的具体使用
May 03 Javascript
详解wepy开发小程序踩过的坑(小结)
May 22 Javascript
vue-cli3跨域配置的简单方法
Sep 06 Javascript
JavaScript设计模式之观察者模式与发布订阅模式详解
May 07 Javascript
vue+elementUI动态增加表单项并添加验证的代码详解
Dec 17 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 Memcached + APC + 文件缓存封装实现代码
2010/03/11 PHP
PHP统计数值数组中出现频率最多的10个数字的方法
2015/04/20 PHP
php实现图片等比例缩放代码
2015/07/23 PHP
Laravel程序架构设计思路之使用动作类
2018/06/07 PHP
Javascript 继承实现例子
2009/08/12 Javascript
Javascript 获取滚动条位置等信息的函数
2009/09/08 Javascript
基于JQuery的模拟苹果桌面Dock效果(稳定版)
2012/10/15 Javascript
JQuery打造省市下拉框联动效果
2014/05/18 Javascript
HTML5游戏引擎LTweenLite实现的超帅动画效果(附demo源码下载)
2016/01/26 Javascript
JavaScript的ExtJS框架中表格的编写教程
2016/05/21 Javascript
JS在Chrome浏览器中showModalDialog函数返回值为undefined的解决方法
2016/08/03 Javascript
浅谈react受控组件与非受控组件(小结)
2018/02/09 Javascript
vue mint-ui tabbar变组件使用
2018/05/04 Javascript
RequireJS用法简单示例
2018/08/20 Javascript
详解js模板引擎art template数组渲染的方法
2018/10/09 Javascript
javascript中关于类型判断的一些疑惑小结
2018/10/14 Javascript
vue两组件间值传递 $router.push实现方法
2019/05/15 Javascript
利用JS代码自动删除稿件的普通弹幕功能
2019/09/20 Javascript
jQuery 选择器用法基础入门示例
2020/01/04 jQuery
pandas dataframe的合并实现(append, merge, concat)
2019/06/24 Python
Python下应用opencv 实现人脸检测功能
2019/10/24 Python
Python基于template实现字符串替换
2020/11/27 Python
利用Canvas模仿百度贴吧客户端loading小球的方法示例
2017/08/13 HTML / CSS
html5 worker 实例(一) 为什么测试不到效果
2013/06/24 HTML / CSS
Speedo速比涛中国官方网站:全球领先泳装运动品牌
2018/04/24 全球购物
Java的for语句中break, continue和return的区别
2013/12/19 面试题
一名毕业生的自我鉴定
2013/12/04 职场文书
周鸿祎:教你写创业计划书
2013/12/30 职场文书
大四学生思想汇报
2014/01/13 职场文书
大学应届毕业生求职信
2014/05/24 职场文书
班风口号
2014/06/18 职场文书
井冈山红色之旅心得体会
2014/10/07 职场文书
2014年大学生村官工作总结
2014/11/19 职场文书
大学生村官工作心得体会
2016/01/23 职场文书
css3中2D转换之有趣的transform形变效果
2022/02/24 HTML / CSS
10大幻兽系恶魔果实 蝙蝠果实上榜,第一自愈能力强
2022/03/18 日漫