Skip to content

<script setup>

在深入研究 <script setup> 语法及其含义之前,我们先快速回顾一下两个概念—— 单文件 组件和组合式 API。

在 Vue 中,单文件组件允许我们在一个单独的 .vue 文件中定义组件的 HTML CSS 和 JS,从而帮助我们组织程序的逻辑。单文件组件由三个部分组成:

vue
<template>
  <!-- HTML 模板写在这 -->
</template>

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

<style>
  /* CSS 样式写在这 */
</style>

<template> 包含组件的原始 HTML,<script> 导出了一个包含该组件全部 JS 逻辑的对象的构造函数,<style> 包含组件全部的样式。

组合式 API 提供了一系列代表了 Vue 的核心功能的独立函数,这些函数主要在 setup() 中使用。setup() 是组合式 API 的入口点。

vue
<!-- 模板 略 -->
<script>
  export default {
    name: "MyComponent",
    setup() {
      // setup 函数
    },
  };
</script>

<!-- 样式 略 -->

确保已经阅读过 组合式,以深入了解组合式 API 对于传统的选项式 API 所具有的优势。

<script setup>

<script setup> 是 Vue 的编译时语法糖,允许使用一种简洁高效的方式通过组合式 API 来定义 Vue 实例。根据 Vue 的官方文档,如果同时使用单文件组件和组合式 API,这是最推荐的语法。

通过 <script setup>,我们可以把我们的组件逻辑压缩到一个单独的代码块中,无需显式调用 setup() 函数。要使用 <script setup>,我们只需要向 <script> 标签中添加 setup 属性。

vue
<script setup>
  // ...
</script>

我们来看一下 <script setup> 语法的主要特点。

无返回值

<script setup> 中,我们不需要在 JS 代码的最后提供返回值。在上面声明的值(方法、变量、导入等)都可以在模板中直接使用。

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

无需显式引入组件

导入的组件会自动识别和解析,不需要在组件中显式地使用 components 选项来声明。

vue
<template>
  <ButtonComponent />
</template>

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

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

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

defineProps()

<script setup> 中,可以直接使用 defineProps() 访问 props。

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

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

<script setup>
  const { buttonText } = defineProps({
    buttonText: String,
  });
</script>

defineProps() 还允许我们使用纯 TypeScript 的形式来定义 props。

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

<script setup lang="ts">
  const { buttonText } = defineProps<{ buttonText: string }>();
</script>

要在纯 TypeScript 定义的 props 中提供默认值,我们需要使用 withDefaules() 宏。

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

<script setup lang="ts">
  const { buttonText } = withDefaults(defineProps<{ buttonText: string }>(), {
    buttonText: "Initial button text",
  });
</script>

defineProps 只能在 <script setup> 中使用,并且不需要导入。

defineEmits()

和 props 类似,可以使用 <script setup> 中的 defineEmits() 方法定义自定义事件,并可以通过其返回值直接触发事件。

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

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

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

<script setup>
  const emit = defineEmits(["close"]);
  const closeButton = () => emit("close");
</script>

defineProps, defineEmits 是只能在 <script setup> 中使用的特殊关键字,而且不需要导入即可使用。当 TypeScript 可用时,还可以直接传入类型。

vue
<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>setup()

对于一些具有大量的返回项和注册了很多子组件的大型组件,<script setup> 语法有助于减少大量的样板代码,从而我们可以获得一个更清晰且更集中的组件定义,进而让代码具有更好的可读性,也更易于维护。

vue
<template>
<!-- 模板 -->
</template>
<script>
import { ref, computed, reactive, watch } from 'vue'

import ComponentA from './ComponentA.vue'
import ComponentB from './ComponentB.vue'

export default {
  name: 'MyComponent',
  components: {         
    ComponentA,         
    ComponentB          
  },                    
  setup() {             
    const count = ref(0)
    const doubleCount = computed(() => count.value * 2)
    const increment = () => {
      count.value ++
    }
    const decrement = () => {
      count.value --
    }

    return {          
      count,          
      doubleCount,    
      increment,      
      decrement       
    }
  }
}
</script>
vue
<template>
<!-- 模板 -->
</template>
<script setup> 
import { ref, computed, reactive, watch } from 'vue'

import ComponentA from './ComponentA.vue'
import ComponentB from './ComponentB.vue'

const count = ref(0)
const doubleCount = computed(() => count.value * 2)
const increment = () => {
  count.value ++
}
const decrement = () => {
  count.value --
}
</script>

alt text

除了减少样板代码之外,<script setup> 语法还提供了更好的运行时性能、更好的 IDE 类型推导性能,以及使用 TypeScript 声明 props 和自定义事件的能力。

关于使用 <script setup> 都需要哪些更改,请参阅下面的 Vue 官方文档。

扩展阅读

评论区
评论区空空如也
发送评论
名字
0 / 20
邮箱
0 / 100
评论内容
0 / 140
由于是非实名评论,所以不提供删除功能。如果你需要删除你发送的评论,或者是其他人的评论对你造成了困扰,请 发邮件给我 。同时评论区会使用 AI + 人工的方式进行审核,以达到合规要求。

© thebestxt.cc
辽ICP备16009524号-8
本站所有文章版权所有,转载请注明出处