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 相关文章推荐
JS中showModalDialog关闭子窗口刷新主窗口用法详解
Mar 25 Javascript
详解webpack进阶之loader篇
Aug 23 Javascript
如何理解Vue的render函数的具体用法
Aug 30 Javascript
Bootstrap Table快速完美搭建后台管理系统
Sep 20 Javascript
vue-cli的eslint相关用法
Sep 29 Javascript
React Router v4 入坑指南(小结)
Apr 08 Javascript
深入浅析Vue.js 中的 v-for 列表渲染指令
Nov 19 Javascript
vue + axios get下载文件功能
Sep 25 Javascript
node使用mysql获取数据库数据中文乱码问题的解决
Dec 02 Javascript
JavaScript中的this原理及6种常见使用场景详解
Feb 14 Javascript
vue elementui tree 任意级别拖拽功能代码
Aug 31 Javascript
vue实现广告栏上下滚动效果
Nov 26 Vue.js
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
社区(php&amp;&amp;mysql)六
2006/10/09 PHP
解析PHP中常见的mongodb查询操作
2013/06/20 PHP
一个PHP的ZIP压缩类分享
2014/05/04 PHP
PHP设计模式之建造者模式定义与用法简单示例
2018/08/13 PHP
php版本CKEditor 4和CKFinder安装及配置方法图文教程
2019/06/05 PHP
js控制滚动条缓慢滚动到顶部实现代码
2013/03/20 Javascript
JS 数字转换研究总结
2013/12/26 Javascript
jQuery实现Twitter的自动文字补齐特效
2014/11/28 Javascript
JQuery select(下拉框)操作方法汇总
2015/04/15 Javascript
javascript实现完美拖拽效果
2015/05/06 Javascript
jQuery中prepend()方法使用详解
2015/08/11 Javascript
js实现仿MSN带关闭功能的右下角弹窗代码
2015/09/04 Javascript
jQuery右下角悬浮广告实例
2016/10/17 Javascript
AngularJS动态绑定ng-options的ng-model实例代码
2017/06/21 Javascript
JavaScript原型继承_动力节点Java学院整理
2017/06/30 Javascript
angularjs实现的购物金额计算工具示例
2018/05/08 Javascript
解决vue脚手架项目打包后路由视图不显示的问题
2018/09/20 Javascript
vue如何安装使用Quill富文本编辑器
2018/09/21 Javascript
微信小程序获取用户openid的实现
2018/12/24 Javascript
微信小程序事件 bindtap bindinput代码实例
2019/08/26 Javascript
VUEX 数据持久化,刷新后重新获取的例子
2019/11/12 Javascript
vue实现禁止浏览器记住密码功能的示例代码
2021/02/03 Vue.js
[02:34]DOTA2亚洲邀请赛 BG战队出场宣传片
2015/03/09 DOTA
Windows系统下使用flup搭建Nginx和Python环境的方法
2015/12/25 Python
Python win32com 操作Exce的l简单方法(必看)
2017/05/25 Python
python pandas读取csv后,获取列标签的方法
2018/11/12 Python
CSS实现聊天气泡效果
2020/04/26 HTML / CSS
浅谈HTML5中dialog元素尝鲜
2018/10/15 HTML / CSS
就业推荐自我鉴定
2013/10/06 职场文书
2014年小班元旦活动方案
2014/02/16 职场文书
《理想》教学反思
2014/02/17 职场文书
体育运动口号
2014/06/09 职场文书
走进毛泽东观后感
2015/06/04 职场文书
回门宴新娘答谢词
2015/09/29 职场文书
matplotlib画混淆矩阵与正确率曲线的实例代码
2021/06/01 Python
二维码条形码生成的JavaScript脚本库
2022/07/07 Javascript