Vue3-07

组件事件

在组件模板的表达式中,可以使用 $emit 方法来触发一个自定义事件。

目的是为了让父组件可以监听这个事件,并在事件回调中处理逻辑。

继续使用上一篇文章的 ParentComponent.vueChildComponent.vue 组件。

ParentComponent.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<template>
<div>
<h2>ParentComponent</h2>
<ChildComponent @my-event="handleMyEvent" />
</div>
</template>

<script>
import ChildComponent from './ChildComponent.vue'

export default {
components: {
ChildComponent
},
methods: {
handleMyEvent() {
console.log('handleMyEvent')
}
}
}
</script>

ChildComponent.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<template>
<div>
<h2>ChildComponent</h2>
<button @click="handleClick">click me</button>
</div>
</template>

<script>
export default {
methods: {
handleClick() {
this.$emit('my-event')
}
}
}
</script>

ParentComponent.vue 组件中,我们监听了 ChildComponent.vue 组件中触发的 my-event 事件,并在事件回调中打印了一句话。

ChildComponent.vue 组件中,我们在 handleClick 方法中调用了 $emit 方法,并传递了一个参数,该参数就是我们要触发的事件的名称。

配合 v-model 使用

在 Vue3 中,我们可以使用 v-model 指令来实现双向数据绑定。

例如,我们希望在用户输入的时候,实时的将用户输入的内容显示在页面上。

ParentComponent.vue

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
<template>
<div>
<h2>ParentComponent</h2>
<p>{{ search }}</p>
<ChildComponent @searchEvent="getSearch" />
</div>
</template>

<script>
import ChildComponent from './ChildComponent.vue'

export default {
components: {
ChildComponent
},
data() {
return {
search: ''
}
},
methods: {
getSearch(value) {
this.search = value
}
}
}
</script>

ChildComponent.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<template>
<div>
<h2>ChildComponent</h2>
<input type="text" v-model="search" />
</div>
</template>

<script>
export default {
data() {
return {
search: ''
}
},
watch: {
search(newValue) {
this.$emit('searchEvent', newValue)
}
}
}
</script>

ParentComponent.vue 组件中,我们监听了 ChildComponent.vue 组件中触发的 searchEvent 事件,并在事件回调中将传递过来的参数赋值给了 search 属性。

ChildComponent.vue 组件中,我们在 search 属性上使用了 v-model 指令,这样就可以实现双向数据绑定。

组件数据传递

利用 props 可以将数据从父组件传递到子组件。在这一小节主要是传递一个函数。

ParentComponent.vue

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
<template>
<div>
<h2>ParentComponent</h2>
<p>父元素 {{ massge }}</p>
<ChildComponent title="子组件" :onEvent="dataFn" />
</div>
</template>

<script>
import ChildComponent from './ChildComponent.vue'

export default {
components: {
ChildComponent
},
data() {
return {
massge: ''
}
},
methods: {
dataFn(data) {
this.massge = data
}
}
}
</script>

ChildComponent.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<template>
<div>
<h2>ChildComponent</h2>
<p>{{ title }}</p>
<p>{{ onEvent('数据传递') }}</p>
</div>
</template>

<script>
export default {
data() {
return {
}
},
props: {
title: String,
onEvent: Function
},
}
</script>

透传 Attribute

“透传” 是指将一个组件的属性应用在另一个元素上。

透传属性是指那些没有在 props / emits 中声明的属性或是 v-on 事件监听器。常见的透传属性有 classstyleid 等。

当组件的根元素是一个普通的 HTML 元素时,这些属性会被添加到根元素上。

当然,我们也可以通过 inheritAttrs 选项来关闭这个特性。

ParentComponent.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<template>
<div>
<h2>ParentComponent</h2>
<ChildComponent class="parent" />
</div>
</template>

<script>
import ChildComponent from './ChildComponent.vue'

export default {
components: {
ChildComponent
}
}
</script>

ChildComponent.vue

1
2
3
4
5
6
7
8
9
10
11
<template>
<div>
<h2>ChildComponent</h2>
</div>
</template>

<script>
export default {
inheritAttrs: false
}
</script>