一、defineProps
父组件通过 v-bind 绑定一个数据,然后子组件通过 defineProps 接受传过来的值。
父组件:
<template>
<StudyDefineProps :title="title" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import StudyDefineProps from './views/components/studyDefineProps.vue'
const title = ref('题目')
</script>
1.子组件中接受父组件传过来的值 defineProps
<template>
<div>{{ title }}</div>
<br />
<div>{{ arr }}</div>
</template>
<script setup lang="ts">
import { ref, reactive } from 'vue'
// 接受父组件传过来的值defineProps
defineProps({
title: {
type: String,
default: '标题'
},
arr: {
type: Array,
default: () => [1, 2, 3]
}
})
</script>
结果:
2.结合 ts 使用:运行结果与上方相同
<template>
<div>{{ title }}</div>
<br />
<div>{{ arr }}</div>
</template>
<script setup lang="ts">
import { ref, reactive } from 'vue'
// ts 特有定义默认值 withDefaults,第一个参数为props函数,第二个参数为一个对象设置默认值
withDefaults(
defineProps<{
title: string
arr: number[]
}>(),
{
arr: () => [1, 2, 3]
}
)
</script>
这两种方法接收的值可以在模板中使用,但是不能用 js 调用,会报错。
3.如果想要使用 js 调用,需要一个参数来接收
// 接受父组件传过来的值defineProps
const props = defineProps({
title: {
type: String,
default: '标题'
},
arr: {
type: Array,
default: () => [1, 2, 3]
}
})
console.log('props', props)
结合 ts 调用:
// ts 特有定义默认值 withDefaults,第一个参数为props函数,第二个参数为一个对象设置默认值
const props = withDefaults(
defineProps<{
title: string
arr?: number[]
}>(),
{
arr: () => [1, 2, 3]
}
)
console.log('props', props)
结果:
二、defineEmits
子组件给父组件传参,是通过 defineEmits 派发一个事件。
父组件:在父组件中通过 v-on 绑定一个事件。
<template>
<StudyDefineProps :title="title" @handle-click="handleClick" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import StudyDefineProps from './views/components/studyDefineProps.vue'
const title = ref('题目')
const handleClick = (title: string) => {
console.log('收到', title)
}
</script>
子组件:子组件中使用 defineEmits 注册了一个自定义事件,点击 click 触发 emit 去调用注册的事件,然后传递参数。父组件接受子组件的事件。
<template>
<div>{{ title }}</div>
<br />
<button @click="changeParentData">修改父组件数据</button>
</template>
<script setup lang="ts">
import { ref, reactive } from 'vue'
const props = withDefaults(
defineProps<{
title: string
arr?: number[]
}>(),
{
arr: () => [1, 2, 3]
}
)
const emit = defineEmits(['handleClick'])
const changeParentData = () => {
emit('handleClick', '标题')
}
</script>
打印结果:
结合 ts 使用:
const emit = defineEmits<{
(e: 'handleClick', title: string): void
}>()
三、defineExpose
父组件想要读到子组件的属性可以通过子组件 defineExpose 暴露。
子组件:
<template>
<div>{{ title }}</div>
<br />
<button @click="changeParentData">修改父组件数据</button>
</template>
<script setup lang="ts">
import { ref, reactive } from 'vue'
// ts 特有定义默认值 withDefaults,第一个参数为props函数,第二个参数为一个对象设置默认值
const props = withDefaults(
defineProps<{
title: string
arr?: number[]
}>(),
{
arr: () => [1, 2, 3]
}
)
const emit = defineEmits<{
(e: 'handleClick', title: string): void
}>()
const changeParentData = () => {
emit('handleClick', '标题')
}
defineExpose({
name: '张三',
age: () => console.log(18)
})
</script>
父组件:这样父组件就可以读到了
<template>
<StudyDefineProps ref="studyDefineProps" :title="title" @handle-click="handleClick" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import StudyDefineProps from './views/components/studyDefineProps.vue'
const studyDefineProps = ref<InstanceType<typeof StudyDefineProps>>()
const title = ref('题目')
const handleClick = (title: string) => {
console.log('收到', studyDefineProps.value?.name, studyDefineProps.value?.age)
}
</script>
打印结果: