详解vue3.2中setup语法糖<script lang="ts" setup>
harry1 人气:0前言
介绍 Vue 3 引入了 Composition API 作为一种在 Vue 应用程序中处理反应状态的新方法。您可以按功能(用户、API、表单)对代码进行分组,而不是按功能(数据、计算、方法、监视等)组织代码。这在构建 Vue 应用程序时允许更大的灵活性。我们已经在其他文章中讨论过 Composition(如果您还没有阅读,请查看它们!),但是随着 Vue 3.2 的发布,另一个与 Composition 相关的功能已经稳定发布 - <script setup>
简而言之,<script setup>允许开发人员定义组件而无需从 JavaScript 块中导出任何内容 - 只需定义变量并在模板中使用它们!这种编写组件的风格在很多方面都类似于 Svelte,对于第一次接触 Vue 的人来说,这是一个巨大的改进。
<script lang=“ts“ setup>
<script setup>是一种编译时语法糖,用于在单文件组件 (SFC) 中使用组合 API。如果同时使用 SFC 和组合 API,则这是建议的语法。与正常语法相比,它提供了许多优点:
- 更简洁的代码,更少的样板
- 能够使用纯 TypeScript 声明 props 和发出的事件
- 更好的运行时性能(模板编译为同一作用域中的渲染函数,无需中间代理)
- 更好的 IDE 类型推断性能(语言服务器从代码中提取类型的工作量更少)
<script setup>基本
让我们看一个例子。如果您使用的是 Options API(Vue 2 的标准),那么您的所有单文件组件将如下所示:
<template> <div>Hello, {{ name }}!</div> <input v-model="name" /> <button :disabled="!isNamePresent" @click="submitName">Submit</button> </template> <script> export default { data() { return { name: '' } }, computed: { isNamePresent() { return this.name.length > 0 } }, methods: { submitName() { console.log(this.name) } } } </script>
我们有我们的模板(一个简单的表单)和我们的脚本块。在脚本块中,我们导出一个具有三个键的对象:名称、计算和方法。如果你熟悉 Vue,这对你来说应该很熟悉。现在,让我们切换此代码以使用 Composition API。
<template> <div>Hello, {{ name }}!</div> <input v-model="name" /> <button :disabled="!isNamePresent" @click="submitName">Submit</button> </template> <script> import { ref, computed } from 'vue' export default { setup() { const name = ref('') const isNamePresent = computed(() => name.value.length > 0) function submitName() { console.log(name.value) } return { name, isNamePresent, submitName } } } </script>
我们的组件做的事情和以前完全一样。我们定义了状态(名称)、计算属性(isNamePresent)和提交函数。如果其中任何一个不熟悉,请查看我之前关于 Vue Composition API 的文章。我们不必在要导出的对象中搭建我们的应用程序,而是可以根据需要自由定义变量。这种灵活性还允许我们根据需要从组件中提取重复的逻辑,但在这种情况下,我们的组件非常简单。
但是,我们仍然有那个尴尬的export default说法。我们的代码都存在于 setup 函数中,而其余的实际上只是样板文件。我们不能直接删除它吗?事实上,我们现在可以!这就是
<template> <div>Hello, {{ name }}!</div> <input v-model="name" /> <button :disabled="!isNamePresent" @click="submitName">Submit</button> </template> <script setup> import { ref, computed } from 'vue' const name = ref('') const isNamePresent = computed(() => name.value.length > 0) function submitName() { console.log(name.value) } </script>
让我们来看看这里发生了什么变化。首先,我们在脚本标签中添加了“setup”这个词,这为编写 Vue 组件启用了这种新模式。其次,我们从setup函数中获取我们的代码,并仅用我们的代码替换我们现有的导出对象。一切都按预期工作!
请注意,在脚本标签中声明的所有内容都在组件的模板中可用。这包括非反应性变量或常量,以及实用函数或其他库。这样做的主要好处是您不需要手动将外部文件(例如,Constants.js)绑定为组件的值 - Vue 现在会为您处理这个问题。
基本语法
要选择加入语法,请将该属性添加到块中:setup``<script>
<script setup> console.log('hello script setup') </script>
内部代码被编译为组件函数的内容。这意味着与正常不同,普通仅在首次导入组件时执行一次,每次创建组件的实例时,内部代码都会执行。setup()
顶级绑定向模板公开# 使用 时,其中声明的任何顶级绑定(包括变量、函数声明和导入)都可以直接在模板中使用:<script setup><script setup>
<script setup> // variable const msg = 'Hello!' // functions function log() { console.log(msg) } </script> <template> <div @click="log">{{ msg }}</div> </template>
进口以同样的方式公开。这意味着您可以在模板表达式中直接使用导入的帮助程序函数,而不必通过以下选项公开它:methods
<script setup> import { capitalize } from './helpers' </script> <template> <div>{{ capitalize('hello') }}</div> </template>
Reactivity
需要使用Reactivity API 显式创建响应式状态。与从函数返回的值类似,在模板中引用 ref 时会自动解开包装:setup()
<script setup> import { ref } from 'vue' const count = ref(0) </script> <template> <button @click="count++">{{ count }}</button> </template>
定义组件
使用时<script setup>
,我们不必再手动定义我们导入的组件了。通过将组件导入文件,编译器能够自动将其添加到我们的应用程序中。让我们通过将表单抽象为它自己的组件来更新我们的组件。我们将它命名为 Form.vue。现在,它只是模板,我们稍后会讨论逻辑。
<!-- Form.vue --> <template> <form @submit.prevent="submitHandler"> <label>Name <input type="text" /> </label> <button>Submit</button> </form> </template> <script setup> function submitHandler() { // Do something } </script> <!-- App.vue --> <template> <div>Hello, {{ name }}!</div> <Form /> </template> <script setup> import { ref } from 'vue' import Form from './components/Form.vue' const name = ref('') function submitForm() { console.log(name.value) } </script>
而已!我们的组件现在必须导入到我们的 Vue 文件中,并且它会自动在我们的模板中可用。不再有components块占用我们文件中的空间!
现在,我们需要将name子组件作为道具传递给我们。但是等等,我们不能定义道具!我们没有要添加 props 选项的对象!此外,我们需要发出表单已提交,以便我们可以触发我们的提交。我们如何定义子组件发出的内容?
defineProps和defineEmits 我们仍然可以使用新的辅助方法defineProps和defineEmits. 来自 Vue 文档,“defineProps并且defineEmits是编译器宏,只能在内部使用<script setup>
。它们不需要导入,在<script setup>
处理时会被编译掉。” 这些编译时函数采用与标准键与完整导出对象一起使用的相同参数。让我们更新我们的应用程序以使用defineProps和defineEmits。
<!-- Form.vue --> <template> <form @submit.prevent="submitHandler"> <label>Name <input v-model="name" type="text" /> </label> <button>Submit</button> </form> </template> <script setup> import { computed } from 'vue' const props = defineProps({ modelValue: { type: String, default: '' } }) const emit = defineEmits(['update:modelValue', 'submit']); const name = computed({ get () { return props.modelValue }, set(val) { emit('update:modelValue', val); } }) function submitHandler() { emit('submit') } </script> <!-- App.vue --> <template> <div>Hello, {{ name }}!</div> <Form v-model="name" @submit="submitForm" /> </template> <script setup> import { ref } from 'vue' import Form from './components/Form.vue' const name = ref('') function submitForm() { console.log(name.value) } </script>
让我们来看看这里发生了什么变化。
首先,我们曾经defineProps期望一个 modelValue(在 Vue 3 中与 v-model 一起使用的预期道具)。 然后我们用 定义了我们的发射defineEmits,这样我们既可以报告这个组件发射的内容,也可以访问该emit函数(以前在 `this.$emit 上可用)。 接下来,我们创建一个使用自定义 getter 和设置的计算属性。我们这样做是为了可以轻松地在表单输入中使用 v-model,但这不是必需的。getter 返回我们的 prop,setter 将更新事件发送到我们的父组件。 最后,我们连接了 submitHandler 函数来发出一个提交事件。 我们的 App.vue 组件或多或少与我们离开它时一样,添加v-model="name"了@submit="submitForm"Form 子组件。这样,我们的应用程序再次按预期工作!
其它功能 这里有更多功能可供我们使用,但它们在典型应用程序中的用例较少。
动态组件- 由于我们的组件在模板中立即可用,我们可以在编写动态组件时使用它们(例如)。 命名空间组件- 如果您有许多从同一文件导入的组件,则可以使用import * as Form语法对这些组件进行命名空间。然后,您无需任何额外工作即可访问<Form.Input>或。<Form.Submit> Top-Level Await - 如果您需要将 API 请求作为组件设置的一部分,您可以在组件的顶层自由使用 async/await 语法 - 无需包装在 async 函数中!请记住,使用它的组件必须由组件在外部包裹
要记住的另一点是,您并没有被锁定在使用<script setup>
. 如果您将这种新语法用于组件并遇到无法完成某事的情况,或者只是想对特定情况使用 Options 语法,您可以通过添加一个额外的. 有关这方面的一个很好的例子,请参阅 Vue 文档。
结论
这是 Vue 和 Composition API 向前迈出的一大步。事实上,Evan You 已经公开表示,这是为了成为 Vue 单文件组件未来的标准语法。来自Github 上的讨论: 这有一些历史,因为关于 Composition API 的最初提案表明打算用它完全取代 Options API,但遭到了强烈反对。尽管我们确实相信Composition API 从长远来看有潜力成为“前进的道路”,但我们意识到(1)仍有人机工程学/工具/设计问题需要解决,(2)范式转变不能一天之内完成。在我们可以自信地向所有 Vue 用户推荐新的东西之前,我们需要时间和早期采用者来验证、尝试、采用和试验新范式。
这实质上导致了一个“过渡期”,在此期间我们有意避免将 Composition API 声明为“新方式”,以便我们可以执行验证过程并与主动采用它的用户子集一起构建周围的工具/生态系统。
现在<script setup>
,随着 IDE 工具支持的改进,我们相信 Composition API 已达到为大多数用户提供卓越 DX 和可扩展性的状态。但我们需要时间来达到这一点。
在同一线程的早些时候,Evan 表达了他对 Vue 未来发展的看法:
目前推荐的方法是:
使用 SFC <script setup>
++ 组合 API 使用 VSCode + Volar(或 WebStorm,一旦它支持<script setup>
即将发布) TS 没有严格要求,但如果适用,请使用 Vite 构建工具。
加载全部内容