关于 script-setup
面向使用 Vue 3 单文件组件和 Composition API 的开发者,介绍 `<script setup>` 语法及其用法,涵盖模板绑定、属性、事件和 TypeScript 默认值。
主要功能
- 01顶层绑定自动用于模板
- 02使用 `defineProps()` 和 `defineEmits()`
- 03用 `withDefaults()` 设置 TypeScript 属性默认值
- 04导入组件后无需注册即可使用
适用场景
- 01减少 Vue 组件定义中的样板代码
- 02声明组件属性和事件
- 03在模板中直接使用导入的组件
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ patternsdev/ skills --skill script-setup安装后在 Claude Code 中输入/script-setup确认已加载。
详细介绍
<script setup>
目录
<script setup> 是在 Vue 单文件组件中使用组合式 API 的编译时语法糖。它会自动将顶层绑定暴露给模板,无需显式编写 return 语句,从而减少样板代码。
适用场景
- 在 Vue 3 中同时使用单文件组件和组合式 API 时,推荐使用此语法
- 有助于减少组件定义中的样板代码
使用说明
- 为
<script>标签添加setup属性:<script setup> - 顶层绑定(变量、函数、导入项)会自动在模板中可用,无需
return - 使用
defineProps()和defineEmits()(无需导入)来处理 props 和事件 - 使用
withDefaults()为 TypeScript 中的 prop 设置默认值 - 导入的组件会自动在模板中可用,无需显式注册
详情
在深入了解 <script setup> 语法及其用途之前,我们先快速回顾两个概念——单文件组件和组合式 API。
在 Vue 中,单文件组件(SFC)让我们能够在单个 .vue 文件中定义组件的 HTML、CSS 和 JS,从而将逻辑整合在一起。单文件组件由三个部分组成:
<template>
</template>
<script>
// JavaScript logic goes here
</script>
<style>
/* CSS styles go here */
</style>
<template> 包含以纯 HTML 编写的组件标记,<script> 导出组件对象构造器,其中包含该组件的所有 JS 逻辑,而 <style> 则包含组件的所有样式。
组合式 API 提供了表示 Vue 核心功能的独立函数。这些函数主要在单个 setup() 选项中使用,它是使用组合式 API 的入口。
<script>
export default {
name: "MyComponent",
setup() {
// the setup function
},
};
</script>
请务必阅读 组合式函数指南,深入了解组合式 API 相较于传统选项式 API 语法的优势。
<script setup>
<script setup> 是一种编译时语法糖,可让我们以更简洁、高效的语法通过组合式 API 定义 Vue 选项。根据 Vue 文档,如果同时使用单文件组件和组合式 API,推荐使用此语法。
使用 <script setup> 代码块,我们可以将组件逻辑精简到一个代码块中,无需显式定义 setup() 函数。要使用 <script setup> 语法,只需为 <script /> 代码块添加 setup 属性。
<script setup>
// ...
</script>
下面来看看 <script setup> 带来的一些主要语法差异。
无需 return 语句
使用 <script setup> 语法时,我们不再需要在代码块末尾定义 return 语句。顶层声明的绑定(函数、变量、导入项等)可以直接在模板中访问和使用。
之前
<template>
<div>
<p>Count: {{ count }}</p>
<p>Username: {{ state.username }}</p>
<button @click="increment">Increment Count</button>
</div>
</template>
<script>
import { ref, reactive, onMounted } from "vue";
setup() {
const count = ref(0);
const state = reactive({username: "John"});
const increment = () => {
count.value++;
};
onMounted(() => {
console.log("Component mounted");
});
return {
count,
state,
increment
};
},
</script>
之后
<template>
<div>
<p>Count: {{ count }}</p>
<p>Username: {{ state.username }}</p>
<button @click="increment">Increment Count</button>
</div>
</template>
<script setup>
import { ref, reactive, onMounted } from "vue";
const count = ref(0);
const state = reactive({ username: "John" });
const increment = () => {
count.value++;
};
onMounted(() => {
console.log("Component mounted");
});
</script>
无需在本地注册组件
在 <script setup> 代码块中,导入的组件会自动被识别和解析,无需在 components 选项中显式声明组件。
之前
<template>
<ButtonComponent />
</template>
<script>
import ButtonComponent from "./components/ButtonComponent.vue";
export default {
setup() {
// the setup function
},
components: {
ButtonComponent,
},
};
</script>
之后
<template>
<ButtonComponent />
</template>
<script setup>
import { ButtonComponent } from "./components/Button";
</script>
defineProps()
可以通过 defineProps() 函数直接在 <script setup> 代码块中访问 props。
之前
<template>
<button>{{ buttonText }}</button>
</template>
<script>
export default {
props: {
buttonText: String,
},
};
</script>
之后
<template>
<button>{{ buttonText }}</button>
</template>
<script setup>
const { buttonText } = defineProps({
buttonText: String,
});
</script>
defineProps() 还允许我们使用纯 TypeScript 声明 props 的结构。
<template>
<button>{{ buttonText }}</button>
</template>
<script setup lang="ts">
const { buttonText } = defineProps<{ buttonText: string }>();
</script>
若要为上面的纯类型声明提供 prop 默认值,我们可以使用 withDefaults() 编译器宏。
<template>
<button>{{ buttonText }}</button>
</template>
<script setup lang="ts">
const { buttonText } = withDefaults(defineProps<{ buttonText: string }>(), {
buttonText: "Initial button text",
});
</script>
defineProps 仅在 <script setup> 中可用,且无需导入即可使用。
defineEmits()
与 props 类似,在组件中使用 defineEmits() 函数,可以直接在 <script setup> 代码块中触发自定义事件。
之前
<template>
<button @click="closeButton">Button Text</button>
</template>
<script>
export default {
emits: ["close"],
setup(props, { emit }) {
const closeButton = () => emit("close");
return {
closeButton,
};
},
};
</script>
之后
<template>
<button @click="closeButton">Button Text</button>
</template>
<script setup>
const emit = defineEmits(["close"]);
const closeButton = () => emit("close");
</script>
与 defineProps 类似,defineEmits 是仅在 <script setup> 中可用的特殊关键字,无需导入即可使用。在 TypeScript 环境中使用时,它也允许我们直接传入类型。
<template>
<button @click="closeButton">Button Text</button>
</template>
<script setup lang="ts">
const emit = defineEmits<{ (e: "close"): void }>(["close"]);
const closeButton = () => emit("close");
</script>
<script setup> 与 setup()
对于返回选项众多且注册了许多本地子组件的大型组件,<script setup> 语法有助于减少大量样板代码,从而让组件定义更加简洁、聚焦,进而提高代码库的可读性和可维护性。
除了减少样板代码,<script setup> 语法还能提升运行时性能和 IDE 类型推断性能,并支持使用 TypeScript 声明 props 和触发事件的结构。
关于使用 <script setup> 语法时需要注意的完整变更列表,请参阅下方的 Vue 官方文档。