前言

在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 组件通信的几种方式的文章就介绍到这了,更多相关vue 组件通信内容请搜索Devmax以前的文章或继续浏览下面的相关文章希望大家以后多多支持Devmax!

vue 组件通信的多种方式的更多相关文章

  1. Vue如何指定不编译的文件夹和favicon.ico

    这篇文章主要介绍了Vue如何指定不编译的文件夹和favicon.ico,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  2. vue自定义加载指令v-loading占位图指令v-showimg

    这篇文章主要为大家介绍了vue自定义加载指令和v-loading占位图指令v-showimg的示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  3. vue使用动画实现滚动表格效果

    这篇文章主要为大家详细介绍了vue使用动画实现滚动表格效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  4. 关于Vue 监控数组的问题

    这篇文章主要介绍了Vue 监控数组的示例,主要包括Vue 是如何追踪数据发生变化,Vue 如何更新数组以及为什么有些数组的数据变更不能被 Vue 监测到,对vue监控数组知识是面试比较常见的问题,感兴趣的朋友一起看看吧

  5. Vue子组件props从父组件接收数据并存入data

    这篇文章主要介绍了Vue子组件props从父组件接收数据并存入data的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  6. Vue h函数的使用详解

    本文主要介绍了Vue h函数的使用详解,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  7. VUE响应式原理的实现详解

    这篇文章主要为大家详细介绍了VUE响应式原理的实现,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助

  8. vue+Element ui实现照片墙效果

    这篇文章主要为大家详细介绍了vue+Element ui实现照片墙效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  9. vue+elemet实现表格手动合并行列

    这篇文章主要为大家详细介绍了vue+elemet实现表格手动合并行列,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. iview+vue实现导入EXCEL预览功能

    这篇文章主要为大家详细介绍了iview+vue实现导入EXCEL预览功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

随机推荐

  1. js中‘!.’是什么意思

  2. Vue如何指定不编译的文件夹和favicon.ico

    这篇文章主要介绍了Vue如何指定不编译的文件夹和favicon.ico,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

  3. 基于JavaScript编写一个图片转PDF转换器

    本文为大家介绍了一个简单的 JavaScript 项目,可以将图片转换为 PDF 文件。你可以从本地选择任何一张图片,只需点击一下即可将其转换为 PDF 文件,感兴趣的可以动手尝试一下

  4. jquery点赞功能实现代码 点个赞吧!

    点赞功能很多地方都会出现,如何实现爱心点赞功能,这篇文章主要为大家详细介绍了jquery点赞功能实现代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  5. AngularJs上传前预览图片的实例代码

    使用AngularJs进行开发,在项目中,经常会遇到上传图片后,需在一旁预览图片内容,怎么实现这样的功能呢?今天小编给大家分享AugularJs上传前预览图片的实现代码,需要的朋友参考下吧

  6. JavaScript面向对象编程入门教程

    这篇文章主要介绍了JavaScript面向对象编程的相关概念,例如类、对象、属性、方法等面向对象的术语,并以实例讲解各种术语的使用,非常好的一篇面向对象入门教程,其它语言也可以参考哦

  7. jQuery中的通配符选择器使用总结

    通配符在控制input标签时相当好用,这里简单进行了jQuery中的通配符选择器使用总结,需要的朋友可以参考下

  8. javascript 动态调整图片尺寸实现代码

    在自己的网站上更新文章时一个比较常见的问题是:文章插图太宽,使整个网页都变形了。如果对每个插图都先进行缩放再插入的话,太麻烦了。

  9. jquery ajaxfileupload异步上传插件

    这篇文章主要为大家详细介绍了jquery ajaxfileupload异步上传插件,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. React学习之受控组件与数据共享实例分析

    这篇文章主要介绍了React学习之受控组件与数据共享,结合实例形式分析了React受控组件与组件间数据共享相关原理与使用技巧,需要的朋友可以参考下

返回
顶部