vue3.2的TS写法

一、父传子的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

  • 1
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值