这🍬好甜!Vue3 新语法糖 script setup

3,115 阅读1分钟

基础语法

<script setup>是Vue3.2正式支持的一个语法糖,在<script setup>中的代码就像是在setup()函数中一样,所有顶级变量、函数、导入的组件都会暴露给模板使用(不用return)

使用方法十分简单,在<script>标签上添加setup属性即可:

<template>
  <button @click="handleClick">
</template>

<script setup>
function handleClick() {
  console.log("message in script setup")
}
</script>

传统的<script>只会在组件第一次被导入时执行,而<script setup>会在每一个组件实例被创建时执行

响应式

和传统的<script>一样,创建响应式变量,你需要使用Reactivity API,但你不再需要手动return

<template>
  <button @click="count++">{{ count }}</button>
</template>

<script setup>
import { ref } from "vue"

const count = ref(0)
</script>

组件

导入的组件可以直接使用,你可以把组件名想象成一个变量:

<template>
  <my-comp />
  <MyComp />
</template>

<script setup>
import MyComp from "./MyComp.vue"
</script>

在模板中引入组件时,无论你使用kebab-case还是PascalCase的方式写标签名都是可以运行的,不过vue推荐使用PascalCase的命名方式,因为这样可以帮助你更好的区分自定义组件

动态组件

因为组件是作为变量被引入的,所以我们可以使用使用:is动态绑定组件:

<template>
  <component :is="MyComp">
</template>

<script setup>
import MyComp from "./MyComp.vue"
</script>

递归组件

MyComp.vue可以通过<MyComp />来引用自己

命名空间组件

从一个文件导入多个组件时,你可以使用类似<Foo.Bar />的方式来引用组件

defineProps 和 defineEmits

顾名思义,defineProps()defineEmits()就是在<script setup>中实现propsemits

defineProps()defineEmits()这两个函数接受的值和propsemits接受的值相同

<template>
  <button @click="handleClick">{{ props.text }}</button>
</template>

<script setup>
import { defineProps, defineEmits } from "vue"

// props
const props = defineProps({
  text: String
})

// emits
const emit = defineEmits(["handleClick"])

function handleClick() { /*...*/ }
</script>

defineExpose

在传统的<script>中,我们可以通过ref实例的方法访问子组件,但是在<script setup>中我们不能这么使用了,<script setup>其实就等于一个闭包,里面的内容只有<template>模板可以访问

如果我们要通过ref来访问子组件内容,可以使用defineExpose手动向外部暴露内容

<script setup>
import { defineExpose } from "vue"

const count = 0
defineExpose({
  a
})
</script>

useSlots 和 useAttrs

一般来说,你会在模板中直接通过$slots$attrs来访问slotsattrs,不过当你需要在<script>中使用时,你可以通过useSlotsuseAttrs来获取

<script setup>
import { useSlots, useAttrs } from "vue"

const slots = useSlots()
const attrs = useAttrs()
</script>

<script>一起使用

当你需要一个普通的<script>时(比如声明组件的name),你可以在组件中同时声明<script><script setup>,但只能各声明一个:

<script>
export default({
  name: "MyComp"
})
</script>

<script setup>
const title = "Title"
</script>

顶层await

<script setup>是默认声明async的,类似于async setup()的效果,你可以在<script setup>中直接使用await函数:

<script setup>
const res = await fetch("/api/getData")
</script>

TypeScript 独占特性

props/emit的类型声明

可以使用仅通过类型来声明definePropsdefineEmits

<script lang="ts" setup>
import { defineProps, defineEmits } from "vue"

const props = defineProps<{
  msg: string,
  count?: number
}>()

const emit = defineEmits<{
  (e: 'change', id: number): void
}>()
</script>

为props设置默认值

<script lang="ts" setup>
import { defineProps, withDefaults } from "vue"

interface Props {
  msg?: string, 
  labels?: string[]
}

const props = withDefaults(defineProps<Props>(), {
  msg: "Hello", 
  labels: () => ["one", "two"]
})
</script>

参考资料

# SFC <script setup>