组件通讯

169 阅读2分钟

通讯的目的

通信[2]是发送者通过某种媒体以某种格式来传递信息到接收者,信息以某种形式(如语音、文字)传递。

组件通讯的目的是传递信息,数据是信息的载体,状态是变化的数据[3]。

组件通讯分类

img

  • 父子
  • 兄弟
  • 祖孙

组件通讯方式

  • props/$emit
  • $children/$parent($root)
  • provide/inject
  • refs/ref
  • eventBus
  • vuex等状态管理库
  • localStorage、sessionStorage、indexDB、$route.query||params
  • $attrs/$listeners

props/$emit

直接进行父子组件通讯,祖孙使用props会存在逐级透传问题。

注意:props不可改值

$children/$parent($root)

$parent可以拿到父组件实例(父组件唯一),可以使用:this.$parent.emit(), this.$parent.on(), this.$parent.属性;

$children在vue3中移除了,在vue2中可使用:官网建议应急使用,且$children数组无法保证顺序。

provide/inject

适合祖孙组件间通讯,用以解决props逐级透传问题[1]。

注意:

  1. inject数据非响应式,可以与computed配合使用
  2. inject注入在data(){}之前
  3. 可以使用Symbol()保证key唯一

refs/ref

this.$refs.childern_ref可以拿到子组件实例。// 如果是普通元素,ref指向DOM元素;若是vue组件,则指向vue实例

eventBus、vuex等状态管理库

eventBus适合小项目的中心状态管理, this.$bus.emit()、 this.$bus.on()、this.$bus.off()

eventBus只做了状态变化后的联动处理,状态变化前的异步过程管理未支持。当项目较大时,容易混乱。vuex等状态管理库对状态变化前后都做了支持[3]。

localStorage、sessionStorage、indexDB、$route.query||params

它们也可以拿来实现组件通讯。

localStorage、sessionStorage、indexDB特点:持久化存储,配合JSON.stringify()/JSON.parse()使用;

$attrs/$listeners

单根节点组件会存在$attrs继承透传,多根节点没有自动的attribute透传行为[6]。

props逐级透传问题为什么使用provide/inject而非$attrs透传

  1. provide既可以传递属性,也可以传递方法;$atrrs只能传递属性,$listener传递方法,但$listener在vue3中移除
  2. $attrs有局限性:多根节点无法自动透传;被"消费"后无法继续向下传递。

小结

父子组件通讯适用props/$emit、$children/parent(parent(root)、refs/ref;

兄弟组件通讯可以父组件作为中间人;

祖孙组件通讯推荐provide/inject、$attrs/$listeners

全局中心通信推荐eventBus、vuex等状态管理库

推荐文章

vue中8种组件通信方式, 值得收藏!

面试官:Vue组件间通信方式都有哪些?

参考文献

[1] 依赖注入

[2] 通信

[3] 理解了状态管理,就理解了前端开发的核心

[4] 面试官:Vue组件间通信方式都有哪些?

[5] vue中8种组件通信方式, 值得收藏!

[6] 透传 Attributes