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页面延迟执行一些方法(整理)
Nov 11 Javascript
jquery重复提交请求的原因浅析
May 23 Javascript
jQuery实现渐变下拉菜单的简单方法
Mar 11 Javascript
jQuery提示插件alertify使用指南
Apr 21 Javascript
分享使用AngularJS创建应用的5个框架
Dec 05 Javascript
js canvas实现擦除动画
Jul 16 Javascript
AngularJS使用ng-repeat和ng-if实现数据的删选显示效果示例【适用于表单数据的显示】
Dec 13 Javascript
JS判断两个对象内容是否相等的方法示例
Apr 10 Javascript
使用Dropzone.js上传的示例代码
Oct 10 Javascript
详解基于Vue,Nginx的前后端不分离部署教程
Dec 04 Javascript
vue计算属性+vue中class与style绑定(推荐)
Mar 30 Javascript
Vue与React的区别和优势对比
Dec 18 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
利用static实现表格的颜色隔行显示的代码
2007/09/02 PHP
PHP序列号生成函数和字符串替换函数代码
2012/06/07 PHP
php获得用户ip地址的比较不错的方法
2014/02/08 PHP
PHP json_decode函数详细解析
2014/02/17 PHP
CI框架(CodeIgniter)操作redis的方法详解
2018/01/25 PHP
详解PHP队列的实现
2019/03/14 PHP
Extjs入门之动态加载树代码
2010/04/09 Javascript
一个js拖拽的效果类和dom-drag.js浅析
2010/07/17 Javascript
javascript中运用闭包和自执行函数解决大量的全局变量问题
2010/12/30 Javascript
JS实现匀速运动的代码实例
2013/11/29 Javascript
js生成验证码并直接在前端判断
2015/05/15 Javascript
jquery $.trim()去除字符串空格的实现方法【附图例】
2016/03/30 Javascript
jquery ezUI 双击行记录弹窗查看明细的实现方法
2016/06/01 Javascript
js图片切换具体实现代码
2016/10/13 Javascript
有关suggest快速删除后仍然出现下拉列表的bug问题
2016/12/02 Javascript
JavaScript中双符号的运算详解
2017/03/12 Javascript
jQuery EasyUI之验证框validatebox实例详解
2017/04/10 jQuery
Bootstrap + AngularJS 实现简单的数据过滤字符查找功能
2017/07/27 Javascript
详解Vue-cli代理解决跨域问题
2017/09/27 Javascript
详解Vue.js使用Swiper.js在iOS
2018/09/10 Javascript
2019 年编写现代 JavaScript 代码的5个小技巧(小结)
2019/01/15 Javascript
详解基于iview-ui的导航栏路径(面包屑)配置
2019/02/22 Javascript
react组件基本用法示例小结
2020/04/27 Javascript
使用vue3重构拼图游戏的实现示例
2021/01/25 Vue.js
Python实现基于PIL和tesseract的验证码识别功能示例
2018/07/11 Python
对Python的zip函数妙用,旋转矩阵详解
2018/12/13 Python
python2爬取百度贴吧指定关键字和图片代码实例
2019/08/14 Python
Tensorflow矩阵运算实例(矩阵相乘,点乘,行/列累加)
2020/02/05 Python
python如何查看网页代码
2020/06/07 Python
css3实现的下拉菜单效果示例
2014/01/22 HTML / CSS
2013的个人自我评价
2013/12/26 职场文书
师德师风演讲稿
2014/05/05 职场文书
公安机关党的群众路线教育实践活动剖析材料
2014/10/10 职场文书
导游词创作书写原则以及开场白技巧怎么学?
2019/09/25 职场文书
解决numpy和torch数据类型转化的问题
2021/05/23 Python
Java 数组内置函数toArray详解
2021/06/28 Java/Android