vue 解决兄弟组件、跨组件深层次的通信操作


Posted in Javascript onJuly 27, 2020

兄弟组件之间的通信同样是在项目中经常会遇到的组件间的通信问题之一, 这种问题的最根本方法就是: 把兄弟组件内部的变量提升到一个中央仓库。

借助父级组件链式交互

使子组件1 通过 $emit 通知父级, 父级再通过响应 子组件1 的事件去触发子组件2的事件,这样的链式操作,在子组件不多的时候,但是一个不错的解决方法

子组件1

<template>
 <div>
  <p @click="$emit('fromFirst','来自A组件')">first组件</p>
 </div>
</template>

<script>
 export default {
  name: 'first'
 }
</script>

子组件2

<template>
  子组件2
 <div>{{secondInfo}}</div>
</template>

<script>
export default {
  name: 'second', 
  data() {
    return {
      this.secondInfo: null
    }
  },
 created(){
   this.$on('fromFather', (info) => {
     this.secondInfo = info
   })
 }
}
</script>

父组件

<template>
 <first @fromFirst='handleFromFirst' />
 <second ref='second' /> 
</template>

<script>
import First from './first'
import Scond from './second'
export default {
  components: {First, Second},
  data() {
    return {
      this.secondInfo: null
    }
  },
  methods:{
    handleFromFirst(val) {
      let second = this.$refs.second
      second.$emit('fromFather', val)
    }
  }
}
</script>

子组件1 触发父组件的 fromFirst 事件, 在事件中又触发了子组件2的 fromFather事件,并将从子组件1 传递过来的参数传递给了该事件, 当子组件2 执行该事件的时候,将内部的 secondInfo 改变。这就实现了一个兄弟组件的交互。

这个方式在 react 里面同样也是适用的, 但是如果父组件内包含了多个子组件并包含了复杂的逻辑, 有没有更好的方式来解决这种方式呢。

大部分第一个想到的是 vuex, 当然这在一个业务逻辑、数据复杂的项目中是一个很好的解决方法, 但是想象我们要编写一个通用组件,这个组件可能被用到不同的项目中来, 如果使用 vuex 这就要求每一个使用这个组件的项目中都要使用 vuex, 这显然是不好的。

借助中间文件,充当中央仓库

还好 ES6 的模块机制天然就支持建立一个中央仓库, 当 A 文件使用 import value from './b.js' 来引用 B 文件里面的 value 的时候, 这时就会赋值给 A 文件一个 B 文件的 value 的 只读引用, 当 B 文件里面的 value 的值发生变化的时候, A 文件里面的 value 也会跟着改变。

// lib.js
export let counter = 3;
export function incCounter() {
counter++;
}

// main.js
import { counter, incCounter } from './lib';
console.log(counter); // 3
incCounter();
console.log(counter); // 4

定义一个额外的实例进行一个事件的中转,对于ES6 模块的运行机制已经有了一个讲解,当模块内部发生变化的时候,引入模块的部分同样会发生变化,当又一个额外的实例对加载机制进行引入进行emit与emit与emit与on进行绑定通信,能轻而易举解决问题,通过b->a->c的模式直接过渡。

解决 vue 兄弟组件之间的通信我们同样也可以使用中央仓库的方式来实现。

// store.js 作为中央仓库

import Vue from 'vue'
export default new Vue()

通过 new 一个 vue 的实例当作兄弟组件交互的中央仓库。

父级组件

<template>
 <first/>
 <second/> 
</template>

<script>
import First from './first'
import Scond from './second'
export default {
  components: {First, Second}
}
</script>

父组件只是引入子组件, 不再作为中央仓库来过渡交互。

子组件1

<template>
  <div @click='hanleClick'>子组件1</div>
</template>

<script>
import Store from './store'

export default {
  name: 'first',
  methods: {
    handleClick() {
      Store.$emit('fromFirst', '来自子组件1的传值')
    }
  }
}
</script>

因为我们的目的就是把 Store 作为一个中央仓库,这里我们把 fromFirst 事件添加到了 Store 上面而不是当前组件 this 上。

子组件2

<template>
  子组件2
 <div>{{secondInfo}}</div>
</template>

<script>
import Store from './store'
export default {
  name: 'second', 
  data() {
    return {
      this.secondInfo: null
    }
  },
 created(){
   Store.$on('fromFirst', (info) => {
     this.secondInfo = info
   })
 }
}
</script>

子组件2 里面同样也是使用 Store 实例来监听 fromFirst 事件, 因为子组件1和子组件2里面添加事件和监听事件的是同一个实例,根据我们在上文中分析的 ES6 中的情况, 当 Store 添加了 fromFirst 这个时间之后, Store实例的 $on 就可以监听到这个事件并执行回调。

跨组件深层次交互

上面讲的组件之间的关系是这样的:

vue 解决兄弟组件、跨组件深层次的通信操作

我们可以实现 子组件之间的交互, 但是如果我们遇到这种情况呢?

vue 解决兄弟组件、跨组件深层次的通信操作

孙组件需要跟子组件3 进行交互,还是使用上述的方法可以做到吗? 答案是肯定的,只要能够使用同一个中央仓库,那么不管什么层级的组件复杂度,都是可以实现两者的交互的。

补充知识:Vue组件跨层级通信

正常组件间通信

父->子组件 是通过属性传递

子->父组件 是通过this.$emit()传递

this.$emit()返回的是this,如果需要一些值 可使用callback方式传递

provide 和 inject

这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,

不论组件层次有多深,并在起上下游关系成立的时间里始终生效。

provide 和 inject 绑定并不是可响应的。这是刻意为之的。

然而,如果你传入了一个可监听的对象,那么其对象的属性还是可响应的。

provide提供数据,多层子组件 向上层寻找,只要找到 就不在向上层寻找了.

inject 向子组件注入数据

使用方式

第一种方式(传递对象,使用字符串数组接收)

// 父级组件提供 'foo'
var Provider = {
 provide: {
  foo: 'bar'
 },
 // ...
}

// 子组件注入 'foo'
var Child = {
 inject: ['foo'],
 created () {
  console.log(this.foo) // => "bar"
 }
 // ...
}

第二种方式(传递返回对象的函数, 使用对象接收)

provide() {
 return {
  // 2.6.0 版本之前 通常传递this. 但这样的话 会传递很多用不到的属性
  theme: {
   color: 'xxx' //如果传入可响应的数据,这里的属性还是可响应的
  }
 };
}
inject: {
 //这里可以换成其它名字
 theme: {
  from: "theme", // 数据来源
  default: () => ({}) //降级情况下使用的 value
  //可以是 普通值
  //可以是 对非原始值使用一个工厂方法
 }
}
//正常子组件
this.theme //即可访问
//子组件是函数式组件的使用方式
injections.theme.color

Vue.observable( object )

让一个对象可响应。Vue 内部会用它来处理 data 函数返回的对象。

可以作为最小化的跨组件状态存储器,用于简单的场景

提供数据可改为

provide() {
 //这时提供的theme 则为可响应的数据
 this.theme = Vue.observable({
  color: "blue"
 });
 return {
  theme: this.theme
 };
},

以上这篇vue 解决兄弟组件、跨组件深层次的通信操作就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
在线编辑器中换行与内容自动提取
Apr 24 Javascript
JQuery 图片延迟加载并等比缩放插件
Nov 09 Javascript
Javascript this 的一些学习总结
Aug 31 Javascript
兼容主流浏览器的jQuery+CSS 实现遮罩层的简单代码
Oct 14 Javascript
Jquery简单实现GridView行高亮的方法
Jun 15 Javascript
javascript实现一个网页加载进度loading
Jan 04 Javascript
js获取当前页的URL与window.location.href简单方法
Feb 13 Javascript
vue使用axios跨域请求数据问题详解
Oct 18 Javascript
Node.js学习教程之HTTP/2服务器推送【译】
Oct 31 Javascript
详解VUE-地区选择器(V-Distpicker)组件使用心得
May 07 Javascript
详解vue中v-for的key唯一性
May 15 Vue.js
一篇文章了解正则表达式的替换技巧
Feb 24 Javascript
vue中组件通信详解(父子组件, 爷孙组件, 兄弟组件)
Jul 27 #Javascript
JS的时间格式化和时间戳转换函数示例详解
Jul 27 #Javascript
vue双击事件2.0事件监听(点击-双击-鼠标事件)和事件修饰符操作
Jul 27 #Javascript
vue键盘事件点击事件加native操作
Jul 27 #Javascript
Element Cascader 级联选择器的使用示例
Jul 27 #Javascript
vue 通过绑定事件获取当前行的id操作
Jul 27 #Javascript
Element Rate 评分的使用方法
Jul 27 #Javascript
You might like
饭制《星际争霸》Mod:优化游戏机制 增加新单位
2017/07/02 星际争霸
数组与类使用PHP的可变变量名需要的注意的问题
2013/06/20 PHP
Codeigniter(CI)框架分页函数及相关知识
2014/11/03 PHP
PHP中使用匿名函数操作数据库的例子
2014/11/17 PHP
php 使用html5实现多文件上传实例
2016/10/24 PHP
详谈PHP面向对象中常用的关键字和魔术方法
2017/02/04 PHP
PHP学习记录之数组函数
2018/06/01 PHP
Thinkphp 框架扩展之Widget扩展实现方法分析
2020/04/23 PHP
js类中的公有变量和私有变量
2008/07/24 Javascript
jQuery选择器简明总结(含用法实例,一目了然)
2014/04/25 Javascript
js创建对象的区别示例介绍
2014/07/24 Javascript
为JS扩展Array.prototype.indexOf引发的问题及解决办法
2015/01/21 Javascript
解决js图片加载时出现404的问题
2020/11/30 Javascript
页面间固定参数,通过cookie传值的实现方法
2017/05/31 Javascript
AngularJs点击状态值改变背景色的实例
2017/12/18 Javascript
利用nginx + node在阿里云部署https的步骤详解
2017/12/19 Javascript
vuex的使用及持久化state的方式详解
2018/01/23 Javascript
使用Angular CLI进行单元测试和E2E测试的方法
2018/03/24 Javascript
Angular5中提取公共组件之radio list的实例代码
2018/07/10 Javascript
详解vue-cli脚手架中webpack配置方法
2018/08/22 Javascript
Paypal支付不完全指北
2020/06/04 Javascript
JavaScript实现切换多张图片
2021/01/27 Javascript
[54:30]Liquid vs Newbee 2019国际邀请赛小组赛 BO2 第二场 8.15
2019/08/16 DOTA
Python3多目标赋值及共享引用注意事项
2019/05/27 Python
Python 炫技操作之合并字典的七种方法
2020/04/10 Python
解决keras加入lambda层时shape的问题
2020/06/11 Python
几个数据库方面的面试题
2016/07/01 面试题
给老婆的搞笑检讨书
2014/01/12 职场文书
大学生职业生涯规划范文
2014/01/22 职场文书
制药工程专业个人求职自荐信
2014/01/25 职场文书
绩效管理实施方案
2014/03/19 职场文书
2014年节能降耗工作总结
2014/12/11 职场文书
社区植树节活动总结
2015/02/06 职场文书
消费者理赔投诉书
2015/07/02 职场文书
详解thinkphp的Auth类认证
2021/05/28 PHP
SpringDataJPA在Entity中常用的注解介绍
2021/12/06 Java/Android