前言

在vue中,​ 组件的关系不外乎以下三种:

组件是需要通信的,在开发中,常用到的通信方式有:vuex、eventBus、以及props与emit、$parent与$children,除此之外,还有provide与inject、$attrs与$listeners等。

一、vuex

这个相信大家用的很多了,简单回顾一下:

  • State:放状态的地方
  • Mutation:唯一修改状态的地方,不支持异步
  • Action:通过调用Mutation中的方法来达到修改状态的目的,支持异步
  • Getter:可以理解为计算属性
  • Module:模块,每个模块拥有自己的 state、mutation、action、getter
    简单的使用这里不赘述,提一下module里面的命名空间。

如果希望你的模块具有更高的封装度和复用性,你可以通过添加 namespaced: true 的方式使其成为带命名空间的模块。当模块被注册后,它的所有 getter、action 及 mutation 都会自动根据模块注册的路径调整命名


这样,在使用的时候我们就可以这样用了:

二、eventBus

这个称为‘事件总线’,简单看下是怎么使用的:

  • 初始化
    首先是初始化一个eventBus,可以绑定到vue原型上,也可以绑定到window对象上,还可以抽出来当做一个模块,在需要的时候再引入。这里直接绑定到vue原型上:

  • 创建事件和删除事件
    在需要的组件上创建和删除事件:

  • 触发事件
    最后就是在需要的地方触发事件了

三、props/emit

这个不用多说了,父子通信用的最多的应该就是这个了。当然,如果以子组件为跳板,也可以做到祖孙之间通信,不过比较麻烦。不建议这样操作。

四、$parent/$children

$parent直接访问的就是父实例,而$children则返回的是实例数组。所以我一般都是$parent搭配$refs使用。

五、$attrs/$listeners

这两个可能会用的比较少,来看下官网的介绍:

怎么理解呢,简单来讲就是,$attrs接收除了prop、style、class之外的所有绑定属性,$listeners则接收除了被.native修饰的所有绑定事件。具体来看下例子:

<template><div><p>父组件</p><input type="text" v-model="formData.inputValue" /><p>子组件</p><Son:inputValue="formData.inputValue":otherValue="otherValue"@success="success"@input.native="handleInput"v-bind="$attrs"v-on="$listeners"></Son></div>
</template>
<script>
import Son from "./son.vue";
export default {components: { Son },provide() {return {father: this.formData,};},data() {return {formData: {inputValue: "123",},otherValue: 999,};},methods: {success(data) {console.log(data);},handleInput() {},},
};
</script>
<template><div><input type="text" v-model="inputValue" @change="handleChange" /></div>
</template>
<script>
export default {props: {inputValue: String,},created() {console.log(this.$attrs, "son---$attrs");console.log(this.$listeners, "son---$listeners");},methods: {handleChange() {this.father.inputValue = this.inputValue;},},
};
</script>

按照之前的理解,$attrs应该只能接收到otherValue,$listeners则只能接收到success事件,看下打印结果:

结果确实也是这样的。除此之外,还可传递给孙组件:

<template><div><input type="text" v-model="inputValue" @change="handleChange" /><GrandSon v-bind="$attrs" v-on="$listeners"></GrandSon></div>
</template>
<script>
import GrandSon from "./grandSon.vue";
export default {components: { GrandSon },props: {inputValue: String,},created() {console.log(this.$attrs, "son---$attrs");console.log(this.$listeners, "son---$listeners");},methods: {handleChange() {this.father.inputValue = this.inputValue;},},
};
</script>
<template><div><input type="text" v-model="inputValue" @change="handleChange" /></div>
</template>
<script>
export default {props: {inputValue: String,},created() {console.log(this.$attrs, "grandSon---$attrs");console.log(this.$listeners, "grandSon---$listeners");},methods: {handleChange() {this.father.inputValue = this.inputValue;},},
};
</script>


通过这种方式,祖孙之间也实现了通信。

六、provide/inject

provide/inject可以在一个祖先组件中向它的所有后辈组件注入一个依赖,只要上下游关系成立就能生效。简单的理解就是provide是注入数据,inject是获取数据。所以provide是用于父组件,inject是用于子孙组件。provide应该是一个对象或者返回一个对象的函数,inject应该是一个字符串数组或者一个对象。官网提到这么一句话:

提示:provide 和 inject 绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的 property 还是可响应的。

这句话怎么理解呢?字面理解就是你要想在上下游传递的那个数据是可响应的,那么就应该以对象的形式传递,先试一下以基本数据类型的形式传递,看下例子:
父组件:

<template><div><p>父组件</p><input type="text" v-model="inputValue" /><p>子组件</p><Son></Son><p>孙组件</p><GrandSon></GrandSon></div>
</template>
<script>
import Son from "./son.vue";
import GrandSon from "./grandSon.vue";
export default {components: { Son, GrandSon },provide() {return {father: this.inputValue,};},data() {return {inputValue: "123",};},
};
</script>

子组件:

<template><div><input type="text" v-model="inputValue" @change="handleChange" /></div>
</template>
<script>
export default {inject: ["father"],data() {return {inputValue: "",};},watch: {father(val) {console.log(val, "val");this.inputValue = val;},},created() {console.log(this, "this");},methods: {handleChange() {this.father.inputValue = this.inputValue;},},
};
</script>

在子组件打印this:

可以看到,父组件的inputValue值是被注入到子组件当中的。但却监听不到这个father。

然后,我们改成以对象的形式进行注入:

<template><div><p>父组件</p><input type="text" v-model="formData.inputValue" /><p>子组件</p><Son></Son><p>孙组件</p><GrandSon></GrandSon></div>
</template>
<script>
import Son from "./son.vue";
import GrandSon from "./grandSon.vue";
export default {components: { Son, GrandSon },provide() {return {father: this.formData,};},data() {return {formData: {inputValue: "123",},};},
};
</script>
<template><div><input type="text" v-model="inputValue" @change="handleChange" /></div>
</template>
<script>
export default {inject: ["father"],data() {return {inputValue: "",};},watch: {'father.inputValue'(val){console.log(val, "val");this.inputValue = val;},},created() {console.log(this, "this");},methods: {handleChange() {this.father.inputValue = this.inputValue;},},
};
</script>

这个时候我们看下打印的this以及效果:


这样就可以实现数据的响应了。这里有一个点需要注意,如果在父组件中将整个父组件的this注入到后代组件中,在后代组件中是不能通过深度监听来监听这个注入的对象的,会报堆栈溢出的错误。所以这里我用的是this.formData的形式注入。这样在子孙组件中可以通过'father.inputValue'这样的形式监听,也可以通过这样的形式:

father: {handler(val) {console.log(val);},deep: true,},

至于为什么会导致这个问题,我们先看下深度监听的实现方式:

这段注释什么意思呢,简单理解就是vue是通过递归遍历对象里面的每一个属性,将是对象的属性收集起来进行监听。众所周知,递归是很容易引起堆栈溢出的,而看下this对象就不难理解为什么会导致堆栈溢出了(太多了,而且是层层嵌套下去的)。
以上就是Vue组件通信的几种方式,如果还要在扯一扯,浏览器的缓存也可以作为一种手段。。。

vue 组件通信的几种方式相关推荐

  1. Vue组件通信的五种方式

    Vue组件通信的五种方式 文章目录 Vue组件通信的五种方式 一. props/$emit(父子通信) 二. vuex(组件之间通信) 三. 事件总线EventBus(组件之间通信) 四. provi ...

  2. vue组件通信的几种方式

    vue组件通信的几种方式 最近用vue开发项目,记录一下vue组件间通信几种方式 第一种,父子组件通信 一.父组件向子组件传值 1.创建子组件,在src/components/文件夹下新建一个Chil ...

  3. vue组件通信的八种方式

    一.props / $emit 父组件通过props的方式向子组件传递数据,而通过$emit 子组件可以向父组件通信. 1. 父组件向子组件传值 下面通过一个例子说明父组件如何向子组件传递数据:在子组 ...

  4. vue组件通信的几种方法

    vue中我们最常使用的就是父子之间的通信还有全局数据管理vuex了,下面粗略说一下vue组件通信的几种方法 组件通信的几种方式 1.父子组件通信 2.兄弟组件通信 3.跨多层级组件通信 4.任意组件( ...

  5. 【vue】vue组件传值的三种方式

    前言 vue的组件传值分为三种方式:父传子.子传父.非父子组件传值 引用官网的一句话:父子组件的关系可以总结为 prop 向下传递,事件向上传递 父组件通过 prop 给子组件下发数据,子组件通过事件 ...

  6. laydate组件 无法传值_Vue组件通信的几种方式

    组件是 vue.js最强大的功能之一,而组件实例的作用域是相互独立的,这就意味着不同组件之间的数据无法相互引用.一般来说,组件可以有以下几种关系: 组件之间的关系 如上图所示,A 和 B.B 和 C. ...

  7. vue组件传值的12种方式

    Vue组件间的12种传值方式 当做到比较大的项目时,一个vue文件里面可能要包含上千行代码,这样不利于后期维护与问题定位,抽离成组件就尤其重要了,我在项目中遇到组件的值如何传递的问题,刚开始接触的时候 ...

  8. React中组件通信的几种方式

    首次发表在个人博客 需要组件之进行通信的几种情况 父组件向子组件通信 子组件向父组件通信 跨级组件通信 没有嵌套关系组件之间的通信 1. 父组件向子组件通信 React数据流动是单向的,父组件向子组件 ...

  9. Vue父子组件通信的三种方式 props、@eventName、$on

    前言 vue 开发中,免不了会用到父子组件的通信,比如调用父类组件的方法或者变量:再比如父组件调用子组件的方法:父子组件相互传递数据等,本文主要通过讲解 三种方式(props.evnetName.ev ...

最新文章

  1. HDU 6156 Palindrome Function 数位DP
  2. 大学生计算机课程考试试题,大学生计算机基础课程考试系统研究与实现
  3. java单词按字典排序_最终Java日志字典:开发人员最常记录的单词是什么?
  4. gradle-com.android.build.api.transform.TransformException:Error while generating the main dex list
  5. Version Control
  6. 天池-新冠疫情相似句对判定大赛top6方案及源码
  7. SQL语法中的JOIN类型
  8. c语言判断二叉树是不是二叉排序树_判断
  9. tomcat管理主机
  10. 通过IE私有滤镜让IE6 7 8支持背景透明,内容不透明效果
  11. h5案例欣赏及分析_2019下半年,10个优秀H5案例参考
  12. 微信小程序蓝牙连接TSPL打印机打印图片思路
  13. 曼妙音色要靠煲 多媒体音箱煲机大法
  14. Jade平台的下载与原装
  15. Spark机器学习实验
  16. T32 simulator
  17. Fuchsia OS 编译教程 2019 年版
  18. 《运营力——微信公众号 设计 策划 客服 管理 一册通》导读
  19. Java入门教程(视频)
  20. 计算机网络中请求超时是什么意思,请求超时什么意思

热门文章

  1. Android 区间SeekBar
  2. 2023最新 Office2021专业增强版 手把手教你安装激活教程
  3. python ks检验_python KS-检验(Kolmogorov-Smirnov test) -- 检验数据是否符合某种分布...
  4. 浏览器触发reflow(回流)的操作
  5. 要是我考上北大了.........
  6. 旋转矩阵表示姿态XYZ坐标轴关系
  7. Android 魅族手机消息不显示(进收纳盒)和始终显示一条推送
  8. 方块与收纳盒-计数dp
  9. 如何使用口径正确订购电子书系列
  10. 医院病房E-R图及关系模式