组件通信
Edit me
  • 父子组件通信

  • 兄弟组件通信

  • 跨级组件通信

自定义事件

当子组件需要向父组件传递数据时,就要用到自定义事件。v-on除了可以监听 DOM 事件外,还可以用于组件事件的自定义事件。

子组件用$emit来触发事件,父组件用$on来监听子组件的事件。

范例

使用 v-model

利用v-model和特殊的自定义事件名接收子组件传递的数据

在自定义组件上使用v-model

如果需要用v-model来接受子组件传递的数据,就需要在子组件上释放一个以特殊名称,也就是input命名的事件。这也可以说是一个语法糖,因为也可以简洁地用自定义事件来实现。

范例

利用v-model实现双向绑定(得多看几遍)

范例

v-model还可以用来创建自定义的表单输入组件,进行数据双向绑定。

实现一个具有双向绑定的v-model组件要满足两个要求:

  1. 接收一个 value 属性。
  2. 在有新的value时触发 input 事件。

非父子组件通信

Vue 1.x 的做法

Vue 1.x 的做法

$dispatch 是向上级派发事件,$broadcast是向下级广播事件。一旦发生事件,任何组件都可以接收到,就近原则,而且会在第一次接收到后停止冒泡,除非返回true

但是,这种方法在 Vue 2.x 中已经废弃。

Vue 2.x 的做法

范例

Vue 2.x 利用总线的方式,可以实现各个组件之间的通信。

所谓bus,就是一个空的 Vue 组件,类似中介的作用,信息通过它完成交换。

具体的流程是:

  1. 首先,建立一个空的 Vue 实例,也就是bus。

  2. 在全局组件定义中,为按钮绑定一个点击事件,当监听到点击事件时,会触发 on-message 自定义事件,会传递一个参数。

  3. 创建 Vue 实例 app,在 app 初始化时(也就是 mounted 生命周期),会去监听来自 bus 的事件 on-message。

业务需要时,可以扩展 bus 的选项,包括datamethodscomputed。这非常有利于共享一些通用的信息,比如用户昵称、性别、邮箱、授权 token 等。这样一来,只要在初始化时,让 bus 获取一次,任何时间、任何组件都能去使用它们。

除了这种方法外,还有两种方法实现组件间的通信。

父链和子链

利用$parent来访问父级组件的数据,并进行修改。

示例

子链的话,同样的流程,去利用$children来访问子组件。

这种访问方式是一种递归向上或向下的访问,直至根实例或最内层的组件。

虽然有这样的支持。但是业务中,既不应该让子组件去依赖父组件的数据,也必须避免去主动修改父级组件的数据。理想情况下,还是应该让组件修改自己的状态,在此前提下通过 props$emit去进行通信。

子组件索引

子组件过多时,通过this.$children来遍历出需要的子组件比较困难,特别是考虑到组件动态渲染时,序列是不固定的。因此,Vue 提供了子组件索引的方式。

其实就是在子组件标签上,给子组件指定一个名称。这样就能在父组件通过$refs来访问指定名称的子组件了。

$refs只在组件渲染完成后填充,并且是非响应式的。它仅仅作为一个直接访问子组件的应急方案。应该避免在模板或计算属性中使用$refs。