script-setup

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

<script setup>

<script setup>

Table of Contents

目录

<script setup>
is compile-time syntactic sugar for using the Composition API in Vue single-file components. It eliminates boilerplate by automatically exposing top-level bindings to the template without an explicit
return
statement.
<script setup>
是Vue单文件组件中使用Composition API的编译时语法糖。它通过自动将顶层绑定暴露给模板,无需显式的
return
语句,从而消除了样板代码。

When to Use

适用场景

  • Use this as the recommended syntax when using both SFCs and the Composition API in Vue 3
  • This is helpful for reducing boilerplate in component definitions
  • 当你在Vue 3中同时使用单文件组件(SFC)和Composition API时,这是推荐使用的语法
  • 有助于减少组件定义中的样板代码

Instructions

使用说明

  • Add the
    setup
    attribute to the
    <script>
    tag:
    <script setup>
  • Top-level bindings (variables, functions, imports) are automatically available in the template — no
    return
    needed
  • Use
    defineProps()
    and
    defineEmits()
    (no import needed) for props and events
  • Use
    withDefaults()
    to provide default prop values in TypeScript
  • Imported components are automatically available in the template without explicit registration
  • <script>
    标签添加
    setup
    属性:
    <script setup>
  • 顶层绑定(变量、函数、导入内容)会自动在模板中可用——无需
    return
  • 使用
    defineProps()
    defineEmits()
    (无需导入)处理props和事件
  • 在TypeScript中使用
    withDefaults()
    为props提供默认值
  • 导入的组件会自动在模板中可用,无需显式注册

Details

详细介绍

Before we delve into the
<script setup>
syntax and what it is, let's quickly recap two concepts — single-file components and the Composition API.
In Vue, SFCs help couple logic by giving us the ability to define HTML/CSS and JS of a component all within a single
.vue
file. A single-file component consists of three parts:
html
<template>
  <!-- HTML template goes here -->
</template>

<script>
  // JavaScript logic goes here
</script>

<style>
  /* CSS styles go here */
</style>
<template>
contains the component's markup in plain HTML,
<script>
exports the component object constructor that consists of all the JS logic within that component, and
<style>
contains all the component styles.
The Composition API provides standalone functions representing Vue's core capabilities. These functions are primarily used within a single
setup()
option which serves as the entry point for utilizing the Composition API.
html
<!-- Template -->

<script>
  export default {
    name: "MyComponent",
    setup() {
      // the setup function
    },
  };
</script>

<!-- Styles -->
Be sure to read the Composables guide for a deeper-dive into the advantages the Composition API provides over the traditional Options API syntax.
在深入讲解
<script setup>
语法之前,我们先快速回顾两个概念——单文件组件(SFC)Composition API
在Vue中,单文件组件能够将组件的HTML/CSS和JS逻辑整合到一个**
.vue
**文件中,实现逻辑耦合。单文件组件包含三个部分:
html
<template>
  <!-- HTML模板写在这里 -->
</template>

<script>
  // JavaScript逻辑写在这里
</script>

<style>
  /* CSS样式写在这里 */
</style>
<template>
包含组件的HTML标记,
<script>
导出包含组件所有JS逻辑的组件对象构造函数,
<style>
包含组件的所有样式。
Composition API提供了代表Vue核心能力的独立函数。这些函数主要在单个
setup()
选项中使用,该选项是使用Composition API的入口点。
html
<!-- 模板 -->

<script>
  export default {
    name: "MyComponent",
    setup() {
      // setup函数
    },
  };
</script>

<!-- 样式 -->
请务必阅读组合式函数指南,深入了解Composition API相较于传统Options API语法的优势。

<script setup>

<script setup>

<script setup>
is compile-time syntactic sugar that allows for a more concise and efficient syntax in defining Vue options with the Composition API. According to the Vue documentation, it is the recommended syntax if one is using both SFCs and the Composition API.
By utilizing the
<script setup>
block, we can condense our component logic into a single block, eliminating the need for an explicit
setup()
function. To use the
<script setup>
syntax, we simply need to introduce the
setup
attribute to the
<script />
block.
html
<script setup>
  // ...
</script>
Let's explore some of the main differences in syntax the
<script setup>
provides.
<script setup>
是一种编译时语法糖,允许以更简洁高效的语法结合Composition API定义Vue选项。根据Vue官方文档,如果同时使用单文件组件和Composition API,这是推荐使用的语法。
通过使用
<script setup>
块,我们可以将组件逻辑浓缩到一个块中,无需显式定义
setup()
函数。要使用
<script setup>
语法,只需为
<script />
块添加
setup
属性即可。
html
<script setup>
  // ...
</script>
让我们探讨
<script setup>
提供的一些主要语法差异。

No return statement

无需return语句

With the
<script setup>
syntax, we no longer need to define a
return
statement at the end of our block. Bindings declared at the top level (functions, variables, imports, etc.) are readily accessible and usable in the template.
使用
<script setup>
语法后,我们不再需要在块末尾定义
return
语句。在顶层声明的绑定(函数、变量、导入内容等)可以直接在模板中访问和使用。

Before

之前的写法

html
<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>
html
<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>

After

使用<script setup>后的写法

html
<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>
html
<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>

No locally registered components

无需局部注册组件

Component imports are automatically recognized and resolved within the
<script setup>
block without the need to explicitly declare the component within a
components
option.
<script setup>
块中,组件导入会被自动识别和解析,无需在
components
选项中显式声明组件。

Before

之前的写法

html
<template>
  <ButtonComponent />
</template>

<script>
  import ButtonComponent from "./components/ButtonComponent.vue";

  export default {
    setup() {
      // the setup function
    },
    components: {
      ButtonComponent,
    },
  };
</script>
html
<template>
  <ButtonComponent />
</template>

<script>
  import ButtonComponent from "./components/ButtonComponent.vue";

  export default {
    setup() {
      // setup函数
    },
    components: {
      ButtonComponent,
    },
  };
</script>

After

使用<script setup>后的写法

html
<template>
  <ButtonComponent />
</template>

<script setup>
  import { ButtonComponent } from "./components/Button";
</script>
html
<template>
  <ButtonComponent />
</template>

<script setup>
  import { ButtonComponent } from "./components/Button";
</script>

defineProps()

defineProps()

Props can be accessed directly within the
<script setup>
block by using the
defineProps()
function.
<script setup>
块中,可以直接使用
defineProps()
函数访问props。

Before

之前的写法

html
<template>
  <button>{{ buttonText }}</button>
</template>

<script>
  export default {
    props: {
      buttonText: String,
    },
  };
</script>
html
<template>
  <button>{{ buttonText }}</button>
</template>

<script>
  export default {
    props: {
      buttonText: String,
    },
  };
</script>

After

使用<script setup>后的写法

html
<template>
  <button>{{ buttonText }}</button>
</template>

<script setup>
  const { buttonText } = defineProps({
    buttonText: String,
  });
</script>
defineProps()
also allows us to declare the shape of our props with pure TypeScript.
html
<template>
  <button>{{ buttonText }}</button>
</template>

<script setup lang="ts">
  const { buttonText } = defineProps<{ buttonText: string }>();
</script>
To provide default prop values in the type-only declaration we have above, we can use the
withDefaults()
compiler macro to achieve this.
html
<template>
  <button>{{ buttonText }}</button>
</template>

<script setup lang="ts">
  const { buttonText } = withDefaults(defineProps<{ buttonText: string }>(), {
    buttonText: "Initial button text",
  });
</script>
defineProps
is available only in
<script setup>
and can be used without having to be imported.
html
<template>
  <button>{{ buttonText }}</button>
</template>

<script setup>
  const { buttonText } = defineProps({
    buttonText: String,
  });
</script>
defineProps()
还允许我们使用纯TypeScript声明props的结构。
html
<template>
  <button>{{ buttonText }}</button>
</template>

<script setup lang="ts">
  const { buttonText } = defineProps<{ buttonText: string }>();
</script>
要在上面的纯类型声明中为props提供默认值,我们可以使用
withDefaults()
编译器宏来实现。
html
<template>
  <button>{{ buttonText }}</button>
</template>

<script setup lang="ts">
  const { buttonText } = withDefaults(defineProps<{ buttonText: string }>(), {
    buttonText: "Initial button text",
  });
</script>
defineProps
仅在
<script setup>
中可用,无需导入即可使用。

defineEmits()

defineEmits()

Similar to props, custom events can be emitted directly within the
<script setup>
block by using the
defineEmits()
function in a component.
与props类似,在
<script setup>
块中,可以直接使用
defineEmits()
函数在组件中触发自定义事件。

Before

之前的写法

html
<template>
  <button @click="closeButton">Button Text</button>
</template>

<script>
  export default {
    emits: ["close"],
    setup(props, { emit }) {
      const closeButton = () => emit("close");

      return {
        closeButton,
      };
    },
  };
</script>
html
<template>
  <button @click="closeButton">Button Text</button>
</template>

<script>
  export default {
    emits: ["close"],
    setup(props, { emit }) {
      const closeButton = () => emit("close");

      return {
        closeButton,
      };
    },
  };
</script>

After

使用<script setup>后的写法

html
<template>
  <button @click="closeButton">Button Text</button>
</template>

<script setup>
  const emit = defineEmits(["close"]);
  const closeButton = () => emit("close");
</script>
Like
defineProps
,
defineEmits
is a special keyword available only in
<script setup>
and can also be used without having to be imported. It also allows us to pass in types directly when working within a TypeScript setting.
html
<template>
  <button @click="closeButton">Button Text</button>
</template>

<script setup lang="ts">
  const emit = defineEmits<{ (e: "close"): void }>(["close"]);
  const closeButton = () => emit("close");
</script>
html
<template>
  <button @click="closeButton">Button Text</button>
</template>

<script setup>
  const emit = defineEmits(["close"]);
  const closeButton = () => emit("close");
</script>
defineProps
一样,
defineEmits
是仅在
<script setup>
中可用的特殊关键字,无需导入即可使用。在TypeScript环境中,它还允许我们直接传入类型。
html
<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>
vs.
setup()

<script setup>
vs.
setup()

For larger components that have a large number of returned options and many locally registered child components, the
<script setup>
syntax helps remove a lot of boilerplate code which leads to cleaner and more focused component definitions that subsequently helps make the codebase more readable and maintainable.
Outside of reducing boilerplate, the
<script setup>
syntax also provides better runtime performance, better IDE-type inference performance, and the ability to declare the shape of props and emitted events with TypeScript.
For a full list of changes that need to be kept in mind when working with the
<script setup>
syntax, refer to the official Vue documentation shared below.
对于包含大量返回选项和许多局部注册子组件的大型组件,
<script setup>
语法有助于移除大量样板代码,使组件定义更简洁、更聚焦,进而提高代码库的可读性和可维护性。
除了减少样板代码外,
<script setup>
语法还提供了更好的运行时性能、更优的IDE类型推断性能,以及使用TypeScript声明props和触发事件结构的能力。
有关使用
<script setup>
语法时需要注意的所有变更列表,请参考下方分享的Vue官方文档。

Source

来源

References

参考资料