vue3中组件prop和emit的使用

[TOC]

组件是带有自定义名称的可复用实例,prop向下传递,emit向上传递。

prop向下传递,emit向上传递

组件prop

通过组件prop可以实现父组件向子组件传递数据

命名规则

HTML中的attribute名是大小写不敏感的,所以浏览器会把所有大写字符解释为小写字符。这意味着当你使用DOM中的模板时,camelCase (驼峰命名法) 的prop名需要使用其等价的kebab-case (短横线分隔命名) 命名。

在JavaScript中使用camelCase

1
2
3
4
5
6
const app = Vue.createApp({})

app.component('blog-post', {
props: ['postTitle'],
template: '<h3>{{ postTitle }}</h3>'
})

在HTML中使用kebab-case

1
<blog-post post-title="hello!"></blog-post>

静态动态数据

prop传入一个静态的值:

1
<blog-post title="这是个静态数据"></blog-post>

通过v-bind或简写:动态赋值:

1
2
3
4
5
<!-- 动态赋予一个变量的值 -->
<blog-post :title="post.title"></blog-post>

<!-- 动态赋予一个复杂表达式的值 -->
<blog-post :title="post.title + ' by ' + post.author.name"></blog-post>

类型检查

通常组件prop可以在组件中以简写的形式定义:

1
props: ['title', 'likes', 'isHot', 'categoryIds', 'author']

也可以对每个组件prop指定值的类型,组件prop的类型可以是下列原生构造函数中的一个,当组件prop验证失败的时候,vue将会产生一个控制台的警告。

nullundefined 值会通过任何类型验证

  • String 字符串
  • Number 数值
  • Boolean 布尔值
  • Array 数组
  • Object 对象
  • Date 日期
  • Function 函数
  • Symbol 唯一值
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
// blog-post子组件prop定义
props: {
title: {
type: String,
required: true
},
likes: {
type: Number,
default: 0
},
isHot: {
type: Boolean,
default: false
},
category: {
type: String,
required: true,
validator(value) {
return ['frontend', 'backend', 'devops'].includes(value)
}
},
author: {
type: Object,
default() {
return { name: '佚名', country: '未知' }
}
},
commentIds: {
type
}
}

<!-- 父组件调用blog-post -->
<blog-post :title="post.title" :category:="post.category"
:author="{
name: 'Xiguapengpeng',
country: 'China'
}"
></blog-post>

自定义事件emit

通过自定义事件可以实现子组件向父组件传递数据

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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
<!-- info-modal子组件定义 -->
<template>
<div id="center" v-if="isOpen">
<input type="text" :value="inputName"/>
<input type="text" :value="age"/>
<button @click="closeModal">关闭模态框</button>
</div>
</template>
export default defineComponent({
name: 'info-modal',
data: function () {
return {
isOpen: false
}
},
props: {
inputName: {
type: String,
required: true
},
age: {
type: Number,
required: true
}
},
emits: ['close', 'update:inputName', 'update:age'],
setup(props, context) {
const closeModal = () => {
context.emit('close', !isOpen)
context.emit('update:inputName', props.inputName)
context.emit('update:age', props.age)
}
return {
closeModal
}
}
})

<!-- 父组件调用info-modal -->
<template>
<!-- v-model的作用是父子组件变量双向绑定 -->
<!-- v-model可以创建多个绑定 -->
<info-modal v-model:input-name="username" v-model:age="age" @close="closeClick"></info-modal>
</template>
export default defineComponent({
components: {
InfoModal
},
data () {
return {
username: "xiguapengpeng",
age: 18
}
},
setup(props, context) {
const closeClick = () => {
alert('i am closed')
}
return {
closeClick
}
}
})

v-model绑定

子组件可以进行事件通知以外,还可以使用v-model形成父子组件双向绑定来更新数据,例子参照上面代码