06-子组件通过事件向使用方传递数据

Catalogue
  1. 1. 使用示例
  2. 2. 使用事件抛出一个值
  3. 3. 事件名
  4. 4. 参考资料

先解读下标题

  1. 子组件通过调用$emit来触发一个自定义事件
  2. 使用方通过v-on监听子组件的自定义事件做出响应
  3. 子组件触发事件时,可传递数据到使用方

使用示例

功能描述: 控制所有博文的字号,同时让页面的其它部分保持默认的字号

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
// 子组件
Vue.component('blog-post', {
props: ['post'],
template: `
<div class="blog-post">
<h3>{{ post.title }}</h3>

<!-- 1. 子组件被点击时,发射enlarge-text自定义事件 -->
<button v-on:click="$emit('enlarge-text')">
Enlarge text
</button>
<div v-html="post.content"></div>
</div>
`
})

// 使用方
<div id="blog-posts-events-demo">

<!-- 3. 同时fontSize值变大,字体变大 -->
<div :style="{ fontSize: postFontSize + 'em' }">
<blog-post
v-for="post in posts"
v-bind:key="post.id"
v-bind:post="post"

<!-- 2.监听enlarge-text自定义事件,并将postFontSize加大 -->
v-on:enlarge-text="postFontSize += 0.1"
></blog-post>
</div>
</div>

new Vue({
el: '#blog-posts-events-demo',
data: {
posts: [/* ... */],
postFontSize: 1
}
})

使用事件抛出一个值

有的时候用一个事件来抛出一个特定的值是非常有用的。例如我们可能想让 <blog-post> 组件决定它的文本要放大多少。这时可以使用 $emit 的第二个参数来提供这个值:

1
2
3
<button v-on:click="$emit('enlarge-text', 0.1)">
Enlarge text
</button>

然后当在父级组件监听这个事件的时候,我们可以通过 $event 访问到被抛出的这个值:

1
2
3
4
<blog-post
...
v-on:enlarge-text="postFontSize += $event"
></blog-post>

或者,如果这个事件处理函数是一个方法:

1
2
3
4
<blog-post
...
v-on:enlarge-text="onEnlargeText"
></blog-post>

那么这个值将会作为第一个参数传入这个方法:

1
2
3
4
5
methods: {
onEnlargeText: function (enlargeAmount) {
this.postFontSize += enlargeAmount
}
}

事件名

不同于组件和 prop,事件名不存在任何自动化的大小写转换。而是触发的事件名需要完全匹配监听这个事件所用的名称。举个例子,如果触发一个 camelCase 名字的事件:

1
this.$emit('myEvent')

则监听这个名字的 kebab-case 版本是不会有任何效果的:

1
2
<!-- 没有效果 -->
<my-component v-on:my-event="doSomething"></my-component>

推荐始终使用 kebab-case 的事件名。

参考资料