本文旨在深入探讨 <script setup> 与 TypeScript 的核心应用方法。
<script setup> 是什么概念?
<script setup> 实际上是单文件组件 (SFC) 中运用 composition api 的一种编译时语法优化形式。
在撰写本文时,vue 所采用的 3.2.26 版本为我们提供了丰富的参考。
接下来,我们将回顾 vue3 <script setup> 的发展轨迹:
- Vue3 在早期版本( 3.0.0-beta.21 之前)对于 composition api 的支持,仅限于在组件选项的 setup 函数中使用。
- 在 3.0.0-beta.21 版本中,Vue 官方引入了 <script setup> 的实验性特性。如果你尝试使用,系统会提示你 <script setup> 仍处于实验阶段。
- 到了 3.2.0 版本,实验状态被正式移除,标志着 <script setup> 正式成为 Vue 框架中稳定可靠的特性之一。
相较于传统的组件选项 setup 函数, <script setup> 具备以下显著优势:
- 代码更为精简,结构更为清晰,无需使用 return {} 暴露变量和方法,组件使用时也无需进行主动注册;
- 对 Typescript 的支持更为完善,使用纯 Typescript 声明 props 和抛出事件,不再像 option api 中那样显得笨拙;
- 运行性能得到显著提升;
当然, <script setup> 也存在自身的局限性,例如需要学习者掌握额外的 API 知识。
那么 <script setup> 应该如何使用?有哪些关键的注意事项?又该如何与 TypeScript 进行有效结合?
Vue3 单文件组件 (SFC) 的 TS IDE 支持可以通过 <script setup lang=”ts”> + VSCode + Volar 来实现。
类型检查则采用 vue-tsc 命令。
- VSCode:作为前端开发领域广受好评的 IDE。
- Volar:专为 Vue3 的 *.vue 文件组件提供代码高亮、语法提示等功能的 VSCode 插件;对于使用 Vue2 的开发者而言,可能更熟悉的是 Vetur 插件,需要将其禁用,并下载安装 Volar 插件。
- vue-tsc:用于类型检查和检查 dts 构建命令行工具。
使用 <script> 代码块时,需要将 setup 属性添加到 <script> 代码块上。
若需使用 TypeScript,则应将 lang 属性添加到 <script> 代码块上,并赋值为 ts。
<script setup> 块中的脚本内容会被编译成组件选项 setup 函数的内部实现,这意味着它会在每次组件实例被创建时执行。
在 <script setup> 中声明的顶层绑定(包括变量、函数、import 引入的内容),都会自动暴露给模板,可直接在模板中使用。
需要注意以下几点:
- 每个 *.vue 文件最多只能同时包含一个 <script> 块 (不包括<script setup>);
- 每个 *.vue 文件最多只能同时包含一个 <script setup> 块 (不包括常规的 <script>);
编译器宏(compiler macros) 包括:defineProps、defineEmits、withDefaults、defineExpose 等。
编译器宏仅限于在 <script setup> 块中使用,无需导入,并且会在处理 <script setup> 块时被一同编译掉。
编译器宏必须在 <script setup> 的顶层使用,不可在 <script setup> 的局部变量中引用。
在 <script setup> 块中,没有组件配置项,即没有 props 选项,需要使用 defineProps 来声明 props 相关信息。defineProps 接收的对象与组件选项 props 的值保持一致。
TS 版本:
从代码示例中可以看出,TS 写法中 props 没有定义默认值。
Vue3 提供了 withDefaults 编译器宏,为 props 提供默认值。
一个需要特别关注的地方:在顶层声明一个与 props 属性同名的变量,可能会引发一些问题。
因此,与组件选项一样,不建议定义与 props 属性同名的顶层变量。
同理,在 <script setup> 块中也没有组件配置项 emits,需要使用 defineEmits 编译器宏来声明 emits 相关信息。
使用组件:
TS 版本:
使用组件:
在 Vue3 中,默认情况下不会暴露任何在 <script setup> 中声明的绑定,即不能通过模板 ref 获取到组件实例声明的绑定。
Vue3 提供了 defineExpose 编译器宏,可以显式地暴露需要暴露的组件中声明的变量和方法。
使用组件:
TS 版本:
使用组件:
在 <script setup> 中常用的辅助函数hooks api,主要包括:useAttrs、useSlots、useCssModule,其他辅助函数尚处于实验阶段,暂不赘述。
在模板中使用 $attrs 来访问 attrs 数据,与 Vue2 相比,Vue3 的 $attrs 还包含了 class 和 style 属性。
在 <script setup> 中使用 useAttrs 函数获取 attrs 数据。
在模板中使用 $slots 来访问 slots 数据。
在 <script setup> 中使用 useSlots 函数获取 slots 插槽数据。
在 Vue3 中,同样支持 CSS Modules,在 <style> 上增加 module 属性,即<style module> 。
<style module> 代码块会被编译为 CSS Modules,并将生成的 CSS 类作为 $style 对象的键暴露给组件,可以直接在模板中使用 $style。对于如 <style module=”content”> 具名 CSS Modules,编译后生成的 CSS 类作为 content 对象的键暴露给组件,即module 属性值什么,就暴露什么对象。
需要注意的是,同名的 CSS Module,后面的会覆盖前面的。
在组件选项中,模板需要使用组件(除了全局组件),需要在 components 选项中进行注册。
而在 <script setup> 中组件无需再注册,模板可以直接使用,实际上相当于一个顶层变量。
建议使用大驼峰(PascalCase)命名组件和使用组件。
<script setup> 没有组件配置项 name,可以再使用一个普通的 <script> 来配置 name。
使用:
注意:如果你设置了 lang 属性,<script setup> 和 <script> 的 lang 需要保持一致。
inheritAttrs 表示是否禁用属性继承,默认值是 true。
<script setup> 没有组件配置项 inheritAttrs,可以再使用一个普通的 <script>。
./components/HelloWorld.vue
<script setup> 中可以使用顶层 await。结果代码会被编译成 async setup()
注意:async setup() 必须与 Suspense 组合使用,Suspense 目前仍是处于实验阶段的特性,其 API 可能随时发生变动,建议暂时不要使用。
在 vue3 中,我们可以使用点语法来使用挂载在一个对象上的组件。
命名空间组件在另一种场景中的使用,从单个文件中导入多个组件时:
Vue3 中 <style> 标签可以通过 v-bind 这一 CSS 函数将 CSS 的值关联到动态的组件状态上。
全局指令:
自定义指令:
导入的指令:
更多关于指令的信息,请参考官方文档。
此语法特性众多,使得单个文件组件更加简洁!只需给 script 标签添加一个 setup 属性,那么整个 script 就会直接变成 setup 函数,所有顶级变量、函数均会自动暴露给模板使用(无需再一个个 return了),开发效率将得到显著提升!
以至于连尤大也在微博上呼吁大家:“如果你能用Vue3却还在用 Options API,现在有了< script setup>没有理由不换 Composition API了”