Skip to content

Vue3.3编译器宏

在vue3.3中,对于defineProps,defineEmits,defineOptions,defineSlots等编译器宏有新的写法。

defineProps

父组件如下,向子组件传入name属性:

vue
<template>
    <div>
        <child :name="['Rarrot']"></child>
    </div>
</template>

<script setup lang='ts'>
import { ref } from 'vue'
import child from './child.vue';
</script>
<style scoped></style>

在子组件进行接收时,用普通写法类型为unkonwn[],其余形式类型为string[]:

vue
<template>
    <div>
        {{ name }}
    </div>
</template>
<script setup lang='ts'>
const props=defineProps({
    name: {
        type: Array,
        required: true
    }
})
props.name
</script>
<style scoped></style>
vue
<template>
    <div>
        {{ name }}
    </div>
</template>
<script setup lang='ts'>
const props3=defineProps<{
    name:string[]
}>()
props3.name
</script>
<style scoped></style>
vue
<template>
    <div>
        {{ name }}
    </div>
</template>
<script setup lang='ts'>
import { PropType } from 'vue'
const props2=defineProps({
    name: {
        type: Array as PropType<string[]>,
        required: true
    }
})
props2.name
</script>
<style scoped></style>
vue
<template>
    <div>
        {{ name }}
    </div>
</template>
<script setup generic="T" lang='ts'>
// 注意script标签上使用了generic="T"
defineProps<{
    name: T,
}>()
props.name
</script>
<style scoped></style>

defineEmits

父组件接收子组件传过来的send点击事件:

vue
<template>
    <div>
        <child @send="getTalk"></child>
    </div>
</template>
<script setup lang='ts'>
import child from './child.vue';
const getTalk = (talk: string) => {
    console.log(talk)
}
</script>
<style scoped></style>

子组件通过defineEmits将点击事件传给父组件:

vue
<template>
    <div>
        <button @click="send">派发事件</button>
    </div>
</template>
<script setup lang='ts'>
const emit = defineEmits(['send'])
const send = () => {
    emit('send', 'hello') 
}
</script>
<style scoped></style>
vue
<template>
    <div>
        <button @click="send">派发事件</button>
    </div>
</template>
<script setup lang='ts'>
const emit = defineEmits<{
    (e: 'send', talk: string): void
}>()
const send = () => {
    emit('send', 'hello') 
}
</script>
<style scoped></style>
vue
<template>
    <div>
        <button @click="send">派发事件</button>
    </div>
</template>
<script setup lang='ts'>
const emit = defineEmits<{
    send: [talk: string]
}>()
const send = () => {
    emit('send', 'hello') 
}
</script>
<style scoped></style>

defineOptions

defineOptions可用于直接在内部 <script setup\> 声明组件选项,而不必使用单独的 <script\> 块,例如自定义name

vue
<script setup>
defineOptions({
    inheritAttrs: false,
    name: 'Rarrot'
})
</script>

defineSlots

  • 仅用作typescript项目中;
  • defineSlots只接受类型参数,不接受运行时参数;
  • 作用:对插槽slot进行类型约束。

子组件提供一个占位符给父组件,并运用defineSlots进行类型约束,子组件如下:

vue
<template>
    <div>
        <ul>
            <li v-for="(item, index) in data">
                <slot :index="index" :item="item"></slot>
            </li>
        </ul>
    </div>
</template>
<script setup generic="T" lang='ts'>
// 接收父组件传过来的list
defineProps<{
    data: T[]
}>()

defineSlots<{
    default(props: { item: T, index: number }): void
}>()
</script>
<style scoped></style>

父组件在子组件提供的占位符中填充模版代码,父组件如下:

vue
<template>
    <div>
        <child :data="list">
            <template #default="{ item,index }">
                {{ item.name }}--{{ index }}
            </template>
        </child>
    </div>
</template>

<script setup lang='ts'>
import child from './child.vue';

const list = [
    {
        name: "张三"
    },
    {
        name: "李四"
    },
    {
        name: "王五"
    }
]
</script>
<style scoped></style>

Released under the MIT License.