单文件组件

返回:api

<script setup>

:::tip <script setup> is a compile-time syntactic sugar(语法糖) for using Composition API inside Single File Components (SFCs). It is the recommended syntax if you are using both SFCs and Composition API. It provides a number of advantages over the normal <script> syntax: :::

  • More succinct code with less boilerplate
  • 更简洁的代码更少的样板文件
  • Ability to declare props and emitted events using pure TypeScript
  • 能够使用纯 typescript 声明道具和触发事件 Better runtime performance (the template is compiled into a render function in the same scope, without an intermediate proxy)
  • 更好的运行时性能(模板被编译为相同范围内的呈现函数,不需要中间代理)
  • Better IDE type-inference performance (less work for the language server to extract types from code)
  • 更好的 IDE 类型推断性能(语言服务器从代码中提取类型的工作量更少)

基本语法

To opt-in to the syntax, add the setup attribute to the <script> block:

<script setup>
console.log("hello script setup");
</script>
  • 内部代码被编译为组件函数的内容。这意味着与普通代码不同,正常程序仅在首次导入组件时执行一次,而内部代码将在每次创建组件的实例时执行。
  • 使用 时,内部声明的任何顶级绑定(包括变量、函数声明和导入)都可以直接在模板中使用
<script setup>
// variable
const msg = "Hello!";

// functions
function log() {
  console.log(msg);
}
</script>

<template>
  <div @click="log">{{ msg }}</div>
</template>
  • 进口以相同的方式公开。这意味着您可以直接在模板表达式中使用导入的帮助程序函数,而无需通过以下选项公开它
<script setup>
import { capitalize } from "./helpers";
</script>

<template>
  <div>{{ capitalize("hello") }}</div>
</template>
  • Reactive state needs to be explicitly created using Reactivity APIs. Similar to values returned from a function, refs are automatically unwrapped(自动解包) when referenced in templates
// count.value
<script setup>
import { ref } from "vue";

const count = ref(0);
</script>

<template>
  <button @click="count++">{{ count }}</button>
</template>
  • Values in the scope of can also be used directly as custom component tag names
  • PascalCase component tags are strongly recommended for consistency. It also helps differentiating from native custom elements.MyComponent<my-component>
<script setup>
import MyComponent from "./MyComponent.vue";
</script>

<template>
  <MyComponent />
</template>
  • Since components are referenced as variables instead of registered under string keys, we should use dynamic binding when using dynamic components inside ::is
  • Note how the components can be used as variables in a ternary expression.
<script setup>
import Foo from "./Foo.vue";
import Bar from "./Bar.vue";
</script>

<template>
  <component :is="Foo" />
  <component :is="someCondition ? Foo : Bar" />
</template>
  • 递归组件
  • 名为的文件可以像在其模板中一样引用自身
  • Note this has lower priority than imported components. If you have a named import that conflicts with the component's inferred name, you can alias the import
import { FooBar as FooBarChild } from './components'
  • This is useful when you import multiple components from a single file
<script setup>
import * as Form from "./form-components";
</script>

<template>
  <Form.Input>
    <Form.Label>label</Form.Label>
  </Form.Input>
</template>

defineProps() & defineEmits()

<script setup>
const props = defineProps({
  foo: String,
});

const emit = defineEmits(["change", "delete"]);
// setup code
</script>

defineExpose()

Components using are closed by default - i.e. the public instance of the component, which is retrieved via template refs or chains, will not expose any of the bindings declared inside

To explicitly expose properties in a component, use the compiler macro

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

const a = 1;
const b = ref(2);

defineExpose({
  a,
  b,
});
</script>
<script setup>
// 获取当前组件实例
const currentInst = getCurrentInstance();

const childShow = () => {
  currentInst.refs.child?.alertMsg();
};
</script>

useSlots() & useAttrs()

Usage of and inside should be relatively rare, since you can access them directly as and in the template. In the rare case where you do need them, use the and helpers respectively

Usage alongside normal <script>

  • Declare options that cannot be expressed in , for example or custom options enabled via plugins.<script setup>inheritAttrs
  • Declaring named exports.
  • Run side effects or create objects that should only execute once.
<script>
// normal <script>, executed in module scope (only once)
runSideEffectOnce()

// declare additional options
export default {
  inheritAttrs: false,
  customOptions: {}
}
</script>

<script setup>
// executed in setup() scope (for each instance)
</script>

Top-level await

Top-level can be used inside . The resulting code will be compiled as

<script setup>
const post = await fetch(`/api/post/1`).then((r) => r.json())
</script>

TypeScript-only Features