温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

vue如何实现组件通信

发布时间:2022-03-03 13:42:54 来源:亿速云 阅读:184 作者:小新 栏目:开发技术

这篇文章主要介绍vue如何实现组件通信,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!

前言

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

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 都会自动根据模块注册的路径调整命名

vue如何实现组件通信

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

vue如何实现组件通信

二、eventBus

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

  • 初始化

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

vue如何实现组件通信

  • 创建事件和删除事件

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

vue如何实现组件通信

  • 触发事件

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

vue如何实现组件通信

三、props/emit

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

四、$parent/$children

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

五、$attrs/$listeners

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

vue如何实现组件通信

怎么理解呢,简单来讲就是,$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事件,看下打印结果:

vue如何实现组件通信

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

<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>

vue如何实现组件通信

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

六、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:

vue如何实现组件通信

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

vue如何实现组件通信

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

<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以及效果:

vue如何实现组件通信

vue如何实现组件通信

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

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

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

vue如何实现组件通信

这段注释什么意思呢,简单理解就是vue是通过递归遍历对象里面的每一个属性,将是对象的属性收集起来进行监听。众所周知,递归是很容易引起堆栈溢出的,而看下this对象就不难理解为什么会导致堆栈溢出了(太多了,而且是层层嵌套下去的)。

以上是“vue如何实现组件通信”这篇文章的所有内容,感谢各位的阅读!希望分享的内容对大家有帮助,更多相关知识,欢迎关注亿速云行业资讯频道!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

vue
AI