-
父子组件通信
-
兄弟组件通信
-
跨级组件通信
自定义事件
当子组件需要向父组件传递数据时,就要用到自定义事件。v-on
除了可以监听 DOM 事件外,还可以用于组件事件的自定义事件。
子组件用$emit
来触发事件,父组件用$on
来监听子组件的事件。
使用 v-model
利用v-model
和特殊的自定义事件名接收子组件传递的数据
在自定义组件上使用v-model
如果需要用v-model
来接受子组件传递的数据,就需要在子组件上释放一个以特殊名称,也就是input
命名的事件。这也可以说是一个语法糖,因为也可以简洁地用自定义事件来实现。
利用v-model
实现双向绑定(得多看几遍)
v-model
还可以用来创建自定义的表单输入组件,进行数据双向绑定。
实现一个具有双向绑定的v-model
组件要满足两个要求:
- 接收一个
value
属性。 - 在有新的
value
时触发 input 事件。
非父子组件通信
Vue 1.x 的做法
$dispatch
是向上级派发事件,$broadcast
是向下级广播事件。一旦发生事件,任何组件都可以接收到,就近原则,而且会在第一次接收到后停止冒泡,除非返回true
。
但是,这种方法在 Vue 2.x 中已经废弃。
Vue 2.x 的做法
Vue 2.x 利用总线的方式,可以实现各个组件之间的通信。
所谓bus,就是一个空的 Vue 组件,类似中介的作用,信息通过它完成交换。
具体的流程是:
-
首先,建立一个空的 Vue 实例,也就是bus。
-
在全局组件定义中,为按钮绑定一个点击事件,当监听到点击事件时,会触发 on-message 自定义事件,会传递一个参数。
-
创建 Vue 实例 app,在 app 初始化时(也就是
mounted
生命周期),会去监听来自 bus 的事件 on-message。
业务需要时,可以扩展 bus 的选项,包括data
、methods
、computed
。这非常有利于共享一些通用的信息,比如用户昵称、性别、邮箱、授权 token 等。这样一来,只要在初始化时,让 bus 获取一次,任何时间、任何组件都能去使用它们。
除了这种方法外,还有两种方法实现组件间的通信。
父链和子链
利用$parent
来访问父级组件的数据,并进行修改。
子链的话,同样的流程,去利用$children
来访问子组件。
这种访问方式是一种递归向上或向下的访问,直至根实例或最内层的组件。
虽然有这样的支持。但是业务中,既不应该让子组件去依赖父组件的数据,也必须避免去主动修改父级组件的数据。理想情况下,还是应该让组件修改自己的状态,在此前提下通过 props
和$emit
去进行通信。
子组件索引
子组件过多时,通过this.$children
来遍历出需要的子组件比较困难,特别是考虑到组件动态渲染时,序列是不固定的。因此,Vue 提供了子组件索引的方式。
其实就是在子组件标签上,给子组件指定一个名称。这样就能在父组件通过$refs
来访问指定名称的子组件了。
$refs
只在组件渲染完成后填充,并且是非响应式的。它仅仅作为一个直接访问子组件的应急方案。应该避免在模板或计算属性中使用$refs。