defineProps、defineEmits、 defineExpose的TS写法
小满视频
1 defineProps:父向子传递数据
作用:父组件向子组件传递数据
1.1 传递纯类型参数的方式来声明
父组件中的代码:
父组件App.vue
<template>
<div>
<span>传递给子组件的响应式数据:</span><input type="text" v-model="sendData">
<hr>
<!-- 2. 使用子组件,添加要传递的数据 -->
<props :sendData="sendData" a="非响应式数据"></props>
</div>
</template>
<script setup lang="ts">
import {ref} from 'vue'
// 1. 引入子组件props
import props from './components/props.vue'
const sendData = ref('')
</script>
子组件代码:
子组件props.vue
<template>
<div>
<p>子组件接收到的数据:</p>
<!-- 4. 插值语法,使用子组件数据 -->
<p>非响应式:{{ a }}</p>
<p>响应式:{{ sendData }}</p>
</div>
</template>
<script setup lang="ts">
import {defineProps} from 'vue'
// 3. 使用defineProps接受父组件传递来的数据
defineProps<{
a:string,
sendData:string
}>()
</script>
1.2 传递数据设置默认值
父组件代码:
父组件App.vue
<template>
<div>
<span>传递给子组件的响应式数据:</span><input type="text" v-model="sendData">
<hr>
<!-- 2. 使用子组件,添加要传递的数据 -->
<props :sendData="sendData" a="非响应式数据"></props>
</div>
</template>
<script setup lang="ts">
import {ref} from 'vue'
// 1. 引入子组件props
import props from './components/props.vue'
const sendData = ref() // 为了演示默认值,修改了这里,在ts中应该指定类型
</script>
子组件代码:
子组件props.vue
<template>
<div>
<p>子组件接收到的数据:</p>
<!-- 4. 插值语法,使用子组件数据 -->
<p>非响应式:{{ a }}</p>
<p>响应式:{{ sendData }}</p>
</div>
</template>
<script setup lang="ts">
import {defineProps} from 'vue'
// 3. 使用defineProps接受父组件传递来的数据
// 只有在使用ts时才能使用withDefaults
withDefaults(defineProps<{
a:string,
sendData:string
}>(),{
sendData:'默认值'
})
</script>
2 defineEmits:子向父传递数据
2.1 使用defineEmits定义事件
子组件代码:
子组件son1.vue
<template>
<div>
子组件<br>
<input type="text" v-model="msg1"><br>
<input type="text" v-model="msg2"><br>
<!-- 2. 定义一个点击事件 -->
<button @click="sendToF">第一种发送方式</button>
<!-- 或者第2步和第3步写在一起. 直接在@click事件中使用emit触发事件clickSend,并传递参数 -->
<button @click="emit('clickSend',[msg1,msg2])">第二种发送方式</button>
</div>
</template>
<script setup lang="ts">
import { ref } from "vue";
const msg1 = ref<string>('')
const msg2 = ref<string>('')
// 1. 使用defineEmits定义一个事件名称
const emit = defineEmits(['clickSend'])
// 3. 在点击事件中使用emit触发事件clickSend,并传递参数
const sendToF = () => {
emit('clickSend',msg1.value)
}
</script>
父组件代码:
父组件App.vue
<template>
<div>
父组件
<div>子组件传来的数据:{{ getData }}</div>
<hr>
<!-- 4. 在父组件中使用@符号绑定子组件中的定义的事件 -->
<son1 @clickSend="son1Data"></son1>
</div>
</template>
<script setup lang="ts">
import { ref } from "vue";
import Son1 from "./components/son1.vue";
const getData = ref<string>('')
// 5. 事件触发后,参数中的值就是子组件传过来的值
const son1Data = (data:string) => {
getData.value = data
}
</script>
第一种发送方式只发送了一个字符串
第二种发送方式发送了一个数组
2.2 传递纯类型参数的方式来声明
子组件代码:
子组件son1.vue
<template>
<div>
子组件<br />
<input type="text" v-model="msg1" /><br />
<input type="text" v-model="msg2" /><br />
<button @click="sendToF">发送</button>
</div>
</template>
<script setup lang="ts">
import { ref } from "vue";
const msg1 = ref<number|"">("");
const msg2 = ref<string>("");
// ts的定义方式
const emit = defineEmits<{
change: [msg1: number|""]; // 具名元组语法
update: [msg2: string];
}>();
// ts的另一种定义方式
/*
const emit = defineEmits<{
(e: 'change', id: number): void
(e: 'update', value: string): void
}>()
*/
const sendToF = () => {
emit("change", msg1.value);
emit("update", msg2.value);
}
</script>
父组件代码:
父组件App.vue
<template>
<div>
父组件:
<div>子组件第一个参数:{{ getData1 }}</div>
<div>子组件第二个参数:{{ getData2 }}</div>
<hr>
<!-- 4. 在父组件中使用@符号绑定子组件中的定义的事件 -->
<son @change="msg1" @update="msg2"></son>
</div>
</template>
<script setup lang="ts">
import { ref } from "vue";
import Son from "./components/son.vue";
const getData1 = ref<number|"">("")
const getData2 = ref<string>()
const msg1 = (msg: number|"") => {
getData1.value = msg
}
const msg2 = (msg: string) => {
getData2.value = msg
}
</script>
3 defineExpose:子向父暴露
- 默认情况下,就算通过引用可以获取到子组件实例,也没有办法获取到子组件中定义的属性和方法
- 子组件可以主动的向外暴露自己的属性和方法
子组件代码
子组件props.vue
<template>
<div>
子组件
</div>
</template>
<script setup lang="ts">
import { ref } from "vue";
const sonData = ref("子组件数据");
const sonFun = () => {
console.log("子组件方法");
}
// 1. 子组件向外暴露组件中的数据和方法
defineExpose({
sonData,
sonFun,
changeSonData: () => {
sonData.value = "子组件暴露的数据被修改";
}
})
</script>
父组件代码:
父组件App.vue
<template>
<div>
<!-- 4. 使用子组件的数据 -->
子组件向外暴露的数据:{{ sonVue?.sonData }}
<br>
<!-- 4. 调用子组件的方法,修改子组件的数据,在父组件中无法直接修改子组件的数据 -->
<button @click="sonVue?.changeSonData()">修改子组件数据</button>
<hr>
<!-- 2. 通过ref属性将sonVue与Son组件关联起来 -->
<Son ref="sonVue"></Son>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from "vue";
import Son from "./components/son.vue";
// 3. 使用ref创建一个指向Son组件实例的引用
const sonVue = ref<InstanceType<typeof Son>>();
onMounted(() => {
// 4. 直接调用子组件方法需要在组件被挂载完毕的时候调用
sonVue.value?.sonFun();
});
</script>
const sonVue = ref<InstanceType< typeof Son>>();
1. Son: 子组件。
2. typeof Son: 表示 Son 组件的类型。
3. InstanceType< typeof Son>: 获取 Son 组件实例的类型。
4. ref<InstanceType< typeof Son>>: 创建一个响应式的引用,其值将是 Son 组件的一个实例。
在 Vue 中,InstanceType 是一个 TypeScript 的实用工具类型,它用于获取类 T 的实例类型。当你定义了一个 Vue 组件并通过 ref 来持有这个组件的实例时,可以使用 InstanceType 来准确地指定类型的实例。