vue3父子组件传值defineProps、defineEmits、defineExpose
一、前言
本文介绍父子组件传值defineProps、defineEmits、defineExpose
二、语法
在 script setup 中必须使用 defineProps 和 defineEmits API 来声明 props 和 emits ,它们具备完整的类型推断并且在 script setup 中是直接可用的
2.1、defineProps
适用于父组件向子组件传递属性
2.1.1、子组件
// 定义Props
const props = defineProps<{
result: number,
name: string
}>()
2.1.2、父组件
<Detail name="结果" :result="1"></Detail>
2.2、带默认值的defineProps
适用于带默认值的Props,经测试不能与defineProps在同一组件同时定义。
2.2.1、子组件
interface IProps {
labels?: string[]
result: number,
name:string
}
// 定义带默认值的Props
const defaultProps = withDefaults(defineProps<IProps>(), {
name: 'hello',
result:0,
labels: () => ['one', 'two']
})
2.2.2、父组件
<!-- 没传的Props会使用子组件的默认值 -->
<Detail name="结果"></Detail>
2.3、defineEmits
适用于父组件向子组件传递方法
2.3.1、子组件
<button @click="btnAdd">添加</button>
<hr />
<button @click="btnReset">重置</button>
<hr />
// 定义Emits
const emits = defineEmits<{
(e: 'add', id: number): void
(e: 'reset', value: number): void
}>()
const btnAdd = () => {
emits('add',2)
}
const btnReset = () => {
emits("reset",0)
}
2.3.2、父组件
<!-- 传入Emits -->
<Detail @add="add" @reset="reset"></Detail>
const result = ref<number>(0);
const add = (num:number)=>{
result.value+=num
}
const reset = (num:number)=>{
result.value = num
}
2.4、defineExpose
适用于子组件向父组件暴露方法和属性,父组件通过子组件示例进行调用。
2.4.1、子组件
// 定义Expose
const exposeStr = ref<string>("")
defineExpose({
exposeStr
})
2.4.2、父组件:
<!-- 传入Props和Emits -->
<Detail ref="detail"></Detail>
// 必须跟组件ref保持一致
const detail = ref()
setTimeout (() => {
detail.value.exposeStr = "exposeStr"
},1000)
三、完整代码
3.1、子组件:detail.vue
<template>
<div>
<!-- {{props.name}} - {{props.result}} -->
<hr />
{{defaultProps.name}} - {{defaultProps.result}} - {{defaultProps.labels}}
<hr />
<button @click="btnAdd">添加</button>
<hr />
<button @click="btnReset">重置</button>
<hr />
{{exposeStr}}
</div>
</template>
<script setup lang="ts">
import { ref,defineProps ,defineEmits,defineExpose} from "vue"
// 定义Props
// const props = defineProps<{
// result: number,
// name: string
// }>()
interface IProps {
labels?: string[]
result: number,
name:string
}
// 定义带默认值的Props
const defaultProps = withDefaults(defineProps<IProps>(), {
name: 'hello',
result:0,
labels: () => ['one', 'two']
})
// 定义Emits
const emits = defineEmits<{
(e: 'add', id: number): void
(e: 'reset', value: number): void
}>()
const btnAdd = () => {
emits('add',2)
}
const btnReset = () => {
emits("reset",0)
}
// 定义Expose
const exposeStr = ref<string>("")
defineExpose({
exposeStr
})
</script>
<style lang="scss" scoped></style>
3.2、父组件:main.vue
<template>
<div>
<!-- 传入Props和Emits -->
<Detail ref="detail" name="结果" :result="result" @add="add" @reset="reset"></Detail>
</div>
</template>
<script setup lang="ts">
import Detail from './detail.vue'
import {ref} from 'vue'
const result = ref<number>(0);
const add = (num:number)=>{
result.value+=num
}
const reset = (num:number)=>{
result.value = num
}
// 必须跟子组件ref名保持一致
const detail = ref()
setTimeout (() => {
// 调用子组件属性并修改值
detail.value.exposeStr = "exposeStr"
},1000)
</script>
本文作者:gaozejie
版权声明:本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。