乐趣区

vue组件中的通信方式

前言

在 vue 中,组件间的通信方式尤为重要。首先,我们来说以下 组件间的关系有哪些呢?父子组件,兄弟组件以及隔代组件。关于父子组件中通信方式,最常用的就是 props,$emit,兄弟组件间的通信方式有 eventBus,vuex 等方式。然而,突然发现还有好几种组件通信的方式未被开启。所以,在这里,总结一下 vue 中的组件通信方式有哪些,每种方式 又都有什么奥妙的地方。

1.props 和 $emit

其实,这种方式是我们在 vue 中经常使用的,对于它的用法就在这里不一一细说了。只说一下关于它的使用的注意事项。
首先,说一下,在父子组件间的通信,数据的流向是单向数据流的。
所有的 prop 都使用的其父子 prop 之间形成一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外改变父级组件的状态,从而导致你的应用的数据流难以理解。
额外的,每次父级组件发生更新时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你不应该在一个子组件内部改变你 prop。如果你这样子做了,vue 会在浏览器的控制台中发出警告。—vue 官方文档。
昨天,看一位同事的代码,突然发现了一个很吊的操作,不是在组件中对父组件中传过来的 props(比如:字符串,数值类型)直接修改会提示错误信息吗?但是对于父组件中传过来的 props(对象),修改其中的某一个属性是不会报错的。所以,利用这一点,在子组件中传入对象的类型,然后修改其中某一个属性。其实,这种操作虽然没有报错,但是其实,在改变子组件中的同时,也改变了父组件中的数据。这种方案还是不可取的。
子组件:在子组件中更改父组件的数据,


父组件:在父组件监听一下,在子组件更改父组件中的数据的时候,父组件中的这个数据是否发生变化。

那有没有什么解决方案呢?

1. 在子组件中定义一个数据,去接收传过来的数据.

2. 如果传入到子组件的数据需要转换的话,可以使用计算属性来实现。3.v-model 的使用方式
在父组件中,子组件绑定 v -model:![clipboard.png](/img/bVbw4QI)
在子组件中,除了要在 props 中声明之外,还需要再 model 中进行声明:![clipboard.png](/img/bVbw4QR)

2.vuex

我们在学习 vue 的同时,也基本会学习使用 vuex,vuex 是一个数据状态管理器,而放在 store 中的数据,是全局状态的,正是因为这个特性,我们可以使用 vuex 进行兄弟组件间的传值。关于 vuex 的使用,大家可以看官网学习一下:https://vuex.vuejs.org/zh/guide/

3.$parent,$children

$parent: 指定已创建的实例之父的实例,在两者之间建立了父子关系。子实例可以通过 this.$parent 访问实例,子实例被推入父实例的 $children 中。
例如:在子组件中打印 this.$parent 的结果是一个对象,里面是父组件的信息:


$children: 当前实例的子组件。例如:在父组件中打印 this.$children 可以获取到一个数组,这个数组里面包含其所有的子组件。

4.$listeners $attrs:

适用于隔代组件,且中间组件只是为了数据的传递。例如:A 组件包含 B 组件,B 组件包含 C 组件。需要将 A 组件中的 message 这个数据传到 C 组件中。常见的写法,就是我们先将 A 组件中的 message 数据传递到 B 组件中,然后再由 B 组件传递到 C 组件。然后,在这里,介绍一种新的写法:#attrs,$listenters.
$attrs 包含了父作用域中不作为 prop 被识别(且获取)的特性绑定(class 和 style 除外)。当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定(class 和 style 除外), 并且可以通过 v -bind=”$attrs” 传入内部组件 – 在创建高级别的组件时非常有用。
emmm… 上面这句话,读着挺绕口的,就是简单来说,将父组件中传入的数据到子组件,然后子组件中没有使用 prop 接收的数据都存放在 $attrs 中,如果想把 $attrs 中的数据传到内部子组件,就可以直接在子组件上 v -bind=”$attrs” 上传入到内部子组件。

A 组件(传入 text1,text2 到 B 组件):

B 组件(只接受了 text1,没有接收 text2, 使用 $attrs 将 text2 传到 C 组件):

C 组件(接收 text2):

结果展示:

上面这个简单的例子,就详情的介绍了一下 $attrs 的使用,这种方式的使用对于隔代组件通信的使用,自我感觉是很方便的。

$listeners: 包含了父作用域中的 (不含.native 修饰器)v-on 事件监听器,它可以通过 v -on=$listeners 传入内部组件 – 在创建更高层次的组件时 sh 非常有用的。
这个属性就是和 $attrs 时类似的,只不过是自定义事件从子组件传到父组件的使用。

5.Provide inject 的使用(主要为高阶插件 / 组件库提供用例。)

provide 选项是一个对象或者返回一个对象的函数。该对象包含可注入其子孙的属性。
inject 选项应该是一个字符串数组或者是一个对象。
这对选项需要一起使用,以允许一个组件组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并且在起上下游关系成立的时间里始终生效。
代码的使用如下图:

6.EventBus: 组件间的通信

EventBus 又称为事件总线。在 Vue 中可以使用 EventBus 来作为沟通桥梁的概念,就像是所有组件共用相同的事件中心,可以向该中心注册发送事件或接收事件,所以组件都可以上下平行地通知其他组件,但也就是太方便所以若使用不慎,就会造成难以维护的灾难,因此才需要更完善的 Vuex 作为状态管理中心,将通知的概念上升到共享状态层次。

7.this.$refs 使用

ref: 被用来给元素或子组件注册引用信息,引用信息将会注册在父组件的 #refs 对象上。
可以通过 $refs 拿到对应组件中想要获取的数据,但是,不建议使用,只有没得办法的时候,在使用。例如,需要操作 dom 节点的时候,或者在组件中,无法通过点击事件获取数据的时候,可以使用 this.$refs


总结

以上就是针对 vue 中组件的通信方式的了解,每种通信方式都有自己的利与弊,我们可以根据项目的实际需求去选择适合的通信方式,切记,滥用。然后哪里写的不对,请多多指教。因为有些方法自己在项目中使用的场景也比较少见,可能会存在偏差,欢迎指出问题!!!

退出移动版