Vue学习系列 -- 告别繁琐,从Vue3的script setup语法糖开始
<script setup>是一种编译时的语法糖,用于在单文件组件(SFC)中使用组合式API。它是推荐的语法,如果你同时使用SFC和组合式API。它提供了一些优点,比如:
- 代码更简洁,减少了样板代码
- 可以使用纯TypeScript声明props和emitted events
- 更好的运行时性能(模板被编译为在同一作用域内的渲染函数,没有中间代理)
- 更好的IDE类型推断性能(语言服务器从代码中提取类型的工作量更少)
使用<script setup>编写Vue单文件组件
Vue单文件组件(SFC)是一种特殊的文件格式,允许我们在一个文件中封装一个Vue组件的模板、逻辑和样式。这是一个简单的SFC示例:
1 | <script> |
我们可以看到,Vue SFC是HTML、CSS和JavaScript这三种经典技术的自然延伸。<template>、<script>和<style>块将一个组件的视图、逻辑和样式封装和放置在同一个文件中。
如果你使用过Vue 2.x,你可能已经熟悉了这种写法。但是,在Vue 3.x中,有了一个新的选择:<script setup>。
什么是<script setup>?
<script setup>是一种编译时的语法糖,用于在单文件组件中使用组合式API。它是推荐的语法,如果你同时使用SFC和组合式API。它提供了一些优点,比如:
- 代码更简洁,减少了样板代码
- 可以使用纯TypeScript声明props和emitted events
- 更好的运行时性能(模板被编译为在同一作用域内的渲染函数,没有中间代理)
- 更好的IDE类型推断性能(语言服务器从代码中提取类型的工作量更少)
要使用这种语法,只需在<script>标签上添加setup属性:
1 | <script setup> |
<script setup>内部的代码会被编译为组件的setup()函数的内容。这意味着与普通的<script>不同,它只在组件第一次导入时执行一次,<script setup>内部的代码会在每次创建组件实例时执行。
如何在<script setup>中使用数据和方法?
当使用<script setup>时,任何在<script setup>内部声明的顶层绑定(包括变量、函数声明和导入)都可以直接在模板中使用:
1 | <script setup> |
导入的模块也可以在模板中直接使用。这意味着你可以直接使用一个导入的辅助函数,而不需要通过methods选项暴露它:
1 | <script setup> |
如何在<script setup>中使用响应式状态?
响应式状态需要使用响应式API显式地创建。类似于从setup()函数返回的值,refs在模板中引用时会自动解包:
1 | <script setup> |
你也可以使用reactive()创建一个响应式对象:
1 | <script setup> |
如何在<script setup>中使用组件?
<script setup>内部的值也可以直接作为自定义组件的标签名使用:
1 | <script setup> |
把MyComponent当作一个变量来引用。如果你用过JSX,这里的思维模型是类似的。模板中的短横线形式<my-component>也可以工作,但是强烈推荐使用帕斯卡命名法的组件标签,以保持一致性。它也有助于区分原生的自定义元素。
如何在<script setup>中使用动态组件?
由于组件是作为变量引用的,而不是注册在字符串键下,所以我们应该使用动态:is绑定来在<script setup>中使用动态组件:
1 | <script setup> |
注意组件可以作为变量在三元表达式中使用。
教程的第二部分可以这样写:
使用TypeScript和自定义类型
如果你想在<script setup>中使用TypeScript,你需要将标签属性改为lang="ts":
1 | <script setup lang="ts"> |
这样就可以享受TypeScript带来的类型检查和自动补全等特性了。
如何在<script setup>中声明props和emitted events?
要声明props,你可以使用defineProps()函数,它接受一个对象参数,表示props的选项。你可以用字符串或者构造函数来指定每个prop的类型,也可以用对象来指定更多的选项,比如默认值、校验器等。例如:
1 | <script setup> |
要声明emitted events,你可以使用defineEmits()函数,它接受一个数组参数,表示emit函数可以触发的事件名。例如:
1 | <script setup> |
这样就可以在<script setup>中使用JS语法来声明props和emitted events了。
如何在<script setup>中使用生命周期钩子?
在<script setup>中,你可以像在普通的setup()函数中一样,使用生命周期钩子函数。你需要从vue模块导入它们,然后在<script setup>内部调用它们。例如:
1 | <script setup> |
注意,你不能在<script setup>内部定义自己的函数来作为生命周期钩子。你必须使用从vue模块导入的函数。这是因为<script setup>内部的代码会被编译为组件的setup()函数的内容,而生命周期钩子必须在setup()函数中调用。
<script setup>的局限性
虽然<script setup>提供了很多便利,但它也有一些局限性,需要我们注意:
<script setup>不能与<script>共存。如果你需要在同一个组件中使用两种语法,你可以将<script setup>放在一个子组件中,然后在父组件中导入它。
<script setup>不能使用src属性。你必须将代码直接写在<script setup>标签内部。
<script setup>不能在函数内部使用defineProps()和defineEmits()。这些函数必须在<script setup>的顶层调用。
<script setup>不能在函数内部定义自己的生命周期钩子。你必须使用从vue模块导入的生命周期钩子函数,并在<script setup>的顶层调用它们。
<script setup>不能使用模板字符串插值。你必须使用普通的字符串拼接或者模板字面量。
<script setup>的注意事项
除了上述的局限性,还有一些注意事项,可以帮助我们更好地使用<script setup>:
<script setup>内部的代码会被编译为组件的setup()函数的内容。这意味着与普通的<script>不同,它只在组件第一次导入时执行一次,<script setup>内部的代码会在每次创建组件实例时执行。
<script setup>内部声明的变量、函数和导入都会被暴露给模板。如果你想隐藏一些内部实现细节,你可以使用下划线前缀来标记它们,例如:_internalValue。这样它们就不会被暴露给模板或者父组件了。
<script setup>内部声明的变量、函数和导入都会被视为响应式依赖。如果你想避免不必要的渲染更新,你可以使用常量前缀来标记它们,例如:const UNREF = 1。这样它们就不会被收集为响应式依赖了。
<script setup>内部声明的变量、函数和导入都会被视为组件选项。如果你想避免与Vue保留的选项名冲突,你可以使用大写字母或者其他符号来命名它们,例如:const $foo = ‘bar’或者const FOO = ‘bar’。
Vue学习系列 -- 告别繁琐,从Vue3的script setup语法糖开始
