一、父传子的TS写法(defineProps)
父组件
<template>
<DefinePropsRuntime title="我是标题" :list="list"/>
</template>
<script lang='ts'>
import DefinePropsRuntime from "./defineProps-runtime.vue"
const list = [
{ id: 1, content: '1' },
{ id: 2, content: '2' }
]
</script>
子组件
<template>
<h1>我是子组件</h1>
<p>{{title}}</p>
<ul>
<li v-for="it in list" :key="it.is">{{ it.content }}</li>
</ul>
</template>
<script lang='ts'>
defineProps<{
title?: string, //加了?:就是可传可不传
list: {id: number, content: string}[], // 这里就是获取一个{id: number, content: string}类型的数组
}>()
</script>
也可以用interface定义{id: number, content: string}
<template>
<h1>我是子组件</h1>
<p>{{title}}</p>
<ul>
<li v-for="it in list" :key="it.is">{{ it.content }}</li>
</ul>
</template>
<script lang='ts'>
interface list {
id: number,
content: string
}
defineProps<{
title?: string, //加了?:就是可传可不传
list: list[], // 这里就是获取一个list类型的数组
}>()
</script>
有没有发现上面用TS写的不可以写默认值,怎么解决呢
用withDefaults:第一个参数是defineProps, 第二个参数是一个对象 对象里面的属性是父组件传值的属性,直接给属性赋值
<template>
<h1>我是子组件</h1>
<p>{{title}}</p>
<ul>
<li v-for="it in list" :key="it.is">{{ it.content }}</li>
</ul>
</template>
<script lang='ts'>
interface list {
id: number,
content: string
}
const props = withDefaults(defineProps<{
title?: string, //加了?:就是可传可不传
list: list[], // 这里就是获取一个list类型的数组
}>(), {
title: "默认值"
})
</script>
二、自定义事件TS写法(defineEmits)
父组件
<template>
<p>{{ count }}</p>
<InfoTs
@parentClick="parentClick"
@parentChange="parentChange"
/>
</template>
<script lang='ts'>
import { ref } from "vue"
import InfoTs from "./info-ts.vue"
const parentClick = () => {
count.value += data;
}
const parentChange = () => {
alert("子组件触发了父组件的parentChange")
}
const count = ref(1)
</script>
子组件
<template>
<button @click="handleClick">触发handleClick事件,并传递2给父组件</button>
<div>
点击触发handleChange事件 <input type="checkbox" name="" id="" @change="handleChange">
</div>
</template>
<script setup lang="ts">
const emit = defineEmits<{
(e: 'parentClick', data: number): void,
(e: 'parentChange'): void
}>();
const handleClick = () => {
emits('parentClick', 2)
}
const handleChange = () => {
emits('handleChange')
}
</script>
总结说明:
const emit = defineEmits<{
(e: 'parentClick', data: number): void,
(e: 'parentChange'): void
}>();
因为defineEmits()返回的是一个函数, 所以我们定义泛型的时候也是定义成函数类型
参数一: e的值是事件名
参数二: data传递的参数,可以给data定义类型
返回值为空就写:void
三、显示的暴露(defineExpose)(不推荐使用 因为这个要操作DOM)
概述:<script setup>的组件下,通过模板属性ref或则$parent链获取到的组件实例,并不会暴露任何在<script setup>中声明的绑定(变量,函数)
为了在<script setup>组件中明确要暴露出去的属性,那么就需要使用defineExpose这个宏命令。
子组件
<template>
<h1>setup</h1>
{{ count }}
</template>
<script setup lang="ts">
import { ref } from "vue"
const count = ref(2);
const handle = () => {
const.log("这个是子组件的方法")
}
defineExpose({
count, // 暴露count属性出去
handle,
})
</script>
父组件
<template>
<InfoSetup ref="InfoRef" />
</template>
<script setup lang="ts">
import { ref, onMounted } from "vue"
import InfoSetup from "./info-setup"
const InfoRef = ref<{count: number, handle: () => void} | null>(null);
onMounted(() => {
console.log(InfoRef.value?.count); // 2 //这里必须放? 因为不确定有没有count
InfoRef.value?.handle()
})
</script>
上面还能更简洁:
子组件
<template>
<h1>setup</h1>
{{ count }}
</template>
// 多加这个
<script lang="ts">
export default {}
</script>
<script setup lang="ts">
import { ref } from "vue"
const count = ref(2);
const handle = () => {
const.log("这个是子组件的方法")
}
</script>
四、useSlots(获取插槽组件的信息)、useAttrs(获取插槽组件属性)
父组件
<template>
<Info class="test" data-a="paopao" :data="1">
<template #header> // 具名插槽 #是v-slot简写
<p>父组件使用了具名插槽</p>
</template>
<template #footer>
<p>父组件使用了 footer具名插槽</p>
</template>
</Info>
</template>
<script setup lang="ts">
import Info from "./info.vue"
</script>
子组件
<template>
<h1>info</h1>
<slot name="header" />
<slot name="footer" />
</template>
<script setup lang="ts">
import { onMounted, useSlots, useAttrs } from "vue";
const slots = useSlots();
const attrs = useAttrs();
onMounted( () => {
// 注意不能直接写slots.header(),要写 slots.header && slots.header(),否则有红色波浪线
console.log(slots.header && slots.header()); // 输出的是插槽名为header的插槽组件信息
console.log(slots.footer && slots.footer()); // 输出的是插槽名为footer的插槽组件信息
console.log(attrs) // 打印出的是插槽组件传进来的全部属性
})
</script>
五、顶层await
await的使用必须要在async语法糖的包裹下,否则将无法执行,为了更简化代码,<script setup> 中可以使用顶层await
旧的写法
使用了顶层await
六、v-bind
略