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学习5 jQuery事件模型
Feb 07 Javascript
基于jQuery的淡入淡出可自动切换的幻灯插件打包下载
Sep 15 Javascript
JavaScript高级程序设计阅读笔记(六) ECMAScript中的运算符(二)
Feb 27 Javascript
javascript分页代码实例分享(js分页)
Dec 13 Javascript
js实现文本框选中的方法
May 26 Javascript
JS实现表单中checkbox对勾选中增加边框显示效果
Aug 21 Javascript
Extjs 点击复选框在表格中增加相关信息行
Jul 12 Javascript
Bootstrap菜单按钮及导航实例解析
Sep 09 Javascript
JS 对java返回的json格式的数据处理方法
Dec 05 Javascript
JSONP基础知识详解
Mar 19 Javascript
ES6 更易于继承的类语法的使用
Feb 11 Javascript
javascript设计模式 ? 访问者模式原理与用法实例分析
Apr 26 Javascript
深入解析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
php4的session功能评述(二)
2006/10/09 PHP
Ajax+PHP实现的模拟进度条功能示例
2019/02/11 PHP
PHP检测一个数组有没有定义的方法步骤
2019/07/20 PHP
Jquery 实现Tab效果 思路是js思路
2010/03/02 Javascript
Javascript实现滚动图片新闻的实例代码
2013/11/27 Javascript
jQuery表格插件ParamQuery简单使用方法示例
2013/12/05 Javascript
JavaScript中原型和原型链详解
2015/02/11 Javascript
JS实现兼容各种浏览器的获取选择文本的方法【测试可用】
2016/06/21 Javascript
详解Vue 开发模式下跨域问题
2017/06/06 Javascript
React复制到剪贴板的示例代码
2017/08/22 Javascript
详解Vue双向数据绑定原理解析
2017/09/11 Javascript
通过封装scroll.js 获取滚动条的值
2018/07/13 Javascript
vue中使用better-scroll实现滑动效果及注意事项
2018/11/15 Javascript
layui lay-verify form表单自定义验证规则详解
2019/09/18 Javascript
JS控制只能输入数字并且最多允许小数点两位
2019/11/24 Javascript
vue滑动吸顶及锚点定位的示例代码
2020/05/10 Javascript
浅析JavaScript预编译和暗示全局变量
2020/09/03 Javascript
解决Python出现_warn_unsafe_extraction问题的方法
2016/03/24 Python
Python序列循环移位的3种方法推荐
2018/04/09 Python
Python使用pyshp库读取shapefile信息的方法
2018/12/29 Python
检测python爬虫时是否代理ip伪装成功的方法
2019/07/12 Python
python+numpy实现的基本矩阵操作示例
2019/07/19 Python
Python编程中类与类的关系详解
2019/08/08 Python
opencv设置采集视频分辨率方式
2019/12/10 Python
Python 支持向量机分类器的实现
2020/01/15 Python
Python如何实现远程方法调用
2020/08/07 Python
CSS3+DIV实现漂亮的动画彩色标签
2016/06/16 HTML / CSS
CSS3属性background-size使用指南
2014/12/09 HTML / CSS
纯CSS3大转盘抽奖示例代码(响应式、可配置)
2017/01/13 HTML / CSS
生物制药自我鉴定
2014/01/25 职场文书
员工团队活动方案
2014/08/28 职场文书
2014年乡镇个人工作总结
2014/12/03 职场文书
考研英语辞职信
2015/05/13 职场文书
2015年测量员工作总结
2015/05/23 职场文书
Python函数中apply、map、applymap的区别
2021/11/27 Python
浅析Python OpenCV三种滤镜效果
2022/04/11 Python