爱客仕-前端团队博客园

浅谈vue父子组件间相互通信

我们都知道Vue 实例实现了一个自定义的事件接口,用于在组件树中通信。这个事件系统独立于原生 DOM 事件,用法也不同。
每个 Vue 实例都是一个事件触发器:

  • 使用 $on() 监听事件;
  • 使用 $emit() 在它上面触发事件;
  • 使用 $dispatch() 派发事件,事件沿着父链冒泡;
  • 使用 $broadcast() 广播事件,事件向下传导给所有的后代。

一、父组件触发子组件内部事件

第一种是通$broadcast广播事件来进行通信

首先,父组件通过$broadcast广播一个parent-msg事件

1
this.$broadcast('parent-msg', '123')

这时子组件可以用以下方式来监听父组件触发的parent-msg事件

1
2
3
events: {
'parent-msg': function (res) {}
}

或者也可以用以下方式来监听

1
this.$on('parent-msg', (res) => {})

二、子组件触发父组件内部事件

第一种是通过$dispatch派发事件来进行通信

首先,子组件通过$dispatch派发一个child-msg事件

1
this.$dispatch('child-msg', '456')

这时父组件可以用以下方式来监听子组件触发的child-msg事件

1
2
3
events: {
'child-msg': function (res) {}
}

或者也可以用以下方式来监听

1
this.$on('child-msg', (res) => {})

第二种

父组件中

1
<v-select v-on:child-msg="handleIt"></v-select>

子组件中通过$emit来触发child-msg事件

1
this.$emit('child-msg', '456')

当子组件触发了child-msg事件,就能触发父组件handleIt事件
父组件中

1
2
3
methods: {
handleIt (res) {}
}

此方法不需要events事件或this.$on来监听事件,因为父组件中已经加了v-on:child-msg来监听子组件的child-msg事件

另外,还有一种子组件传值给父组件的方法

这种方法并不会触发父组件中的事件
主要是通过子组件内部触发事件,通过事件的回调参数来传值

首先,父组件中传递一个function类型的props给子组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<template>
<v-select :on-change="clickInput('123')"></v-select>
</template>
<script>
export default {
methods: {
clickInput (model) {
// model为123
return (option) => {
// option就是从子组件传回的456
}
}
}
}
</script>

子组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
export default {
props: {
onChange: {
type: Function,
default: () => {}
}
},
ready () {
this.handleOptionClick('456')
},
methods: {
handleOptionClick(option) {
this.onChange(option)
}
}
}

子组件接收这个props,然后触发onChange(option),此时父组件中clickInput的回调函数就可以取得这个参数option的值456

通过这种方式,onChange就好像父组件打入子组件内部的间谍,从子组件源源不断的传回值,好像有点猥琐- -

我们看一下vue官网对于prop的介绍:

prop 默认是单向绑定:当父组件的属性变化时,将传导给子组件,但是反过来不会。
这是为了防止子组件无意修改了父组件的状态——这会让应用的数据流难以理解。

我们现在通过这种方式实现子组件传值给父组件,但是这个值并不是父组件中已有的值或者属性,所以并不会导致无意中修改了父组件的状态

ps:有其他遗漏的通信方式,希望能继续补充…