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 相关文章推荐
jcarousellite.js 基于Jquery的图片无缝滚动插件
Dec 30 Javascript
了解一点js的Eval函数
Jul 26 Javascript
通过js简单实现将一个文本内容转译成加密文本
Oct 22 Javascript
Node.js文件操作详解
Aug 16 Javascript
JS密码生成与强度检测完整实例(附demo源码下载)
Apr 06 Javascript
浅析JavaScript中浏览器的兼容问题
Apr 19 Javascript
浅谈Sublime Text 3运行JavaScript控制台
Jun 06 Javascript
谈谈对JavaScript原生拖放的深入理解
Sep 20 Javascript
vue.js 实现输入框动态添加功能
Jun 25 Javascript
Vue中跨域及打包部署到nginx跨域设置方法
Aug 26 Javascript
JavaScript实现沿五角星形线摆动的小圆实例详解
Jul 28 Javascript
vue-cli3访问public文件夹静态资源报错的解决方式
Sep 02 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
将二维数组转为一维数组的2种方法
2014/05/26 PHP
php+ajax实现图片文件上传功能实例
2014/06/17 PHP
一个经典实用的PHP图像处理类分享
2014/11/18 PHP
Yii 框架控制器创建使用及控制器响应操作示例
2019/10/14 PHP
PHP时间相关常用函数用法示例
2020/06/03 PHP
jquery利用event.which方法获取键盘输入值的代码
2011/10/09 Javascript
jquery 插件学习(一)
2012/08/06 Javascript
JS网页图片按比例自适应缩放实现方法
2014/01/15 Javascript
js实现日历可获得指定日期周数及星期几示例分享(js获取星期几)
2014/03/14 Javascript
jQuery检查事件是否触发的方法
2015/06/26 Javascript
Javascript中神奇的this
2016/01/20 Javascript
全面解析Bootstrap中form、navbar的使用方法
2016/05/30 Javascript
JavaScript中Array对象用法实例总结
2016/11/29 Javascript
vuex根据不同的用户权限展示不同的路由列表功能
2019/09/20 Javascript
nodejs使用socket5进行代理请求的实现
2020/02/21 NodeJs
Vue+Element ui 根据后台返回数据设置动态表头操作
2020/09/21 Javascript
python套接字流重定向实例汇总
2016/03/03 Python
Python多层嵌套list的递归处理方法(推荐)
2016/06/08 Python
Zabbix实现微信报警功能
2016/10/09 Python
详谈python3 numpy-loadtxt的编码问题
2018/04/29 Python
python计算两个地址之间的距离方法
2018/06/09 Python
python查找重复图片并删除(图片去重)
2019/07/16 Python
Python使用matplotlib绘制Logistic曲线操作示例
2019/11/28 Python
python实现文字版扫雷
2020/04/24 Python
如何基于Python代码实现高精度免费OCR工具
2020/06/18 Python
Python使用Selenium实现淘宝抢单的流程分析
2020/06/23 Python
python 服务器运行代码报错ModuleNotFoundError的解决办法
2020/09/16 Python
美国领先的户外服装与装备用品店:Moosejaw
2016/08/25 全球购物
Myprotein丹麦官网:欧洲第一运动营养品牌
2019/04/15 全球购物
运动会的口号
2014/06/09 职场文书
法定代表人身份证明书
2014/09/10 职场文书
学院党的群众路线教育实践活动第一阶段情况汇报
2014/10/25 职场文书
通知的写法
2015/04/23 职场文书
迁徙的鸟观后感
2015/06/09 职场文书
校运会通讯稿
2015/07/18 职场文书
「月刊Action」2022年5月号封面公开
2022/03/21 日漫