DEV Community

Cover image for Using two script blocks in Vue Single File Components
Jakub Andrzejewski
Jakub Andrzejewski

Posted on

8

Using two script blocks in Vue Single File Components

Hey there!

I recently encountered an issue while developing Vue components - I wanted to create a component with logic and UI and export from it TypeScript specific entities like interface or enum. The first part I have implemented using the script setup syntax. I didn't know what to do but my friend shared with me a solution to my problem.

Interestingly, this is not some dirty trick but a fully supported and documented feature of Vue that you can read more about here.

In this article, I would like to show you how you can use two script blocks in one Vue component so that you can solve similar problem if you encounter it.

Enjoy!

🟢 Using two script blocks in Vue components

As an example, let's take a look at the following component that will be responsible for creating an element that will be a div with a letter. It will accept two props letter and size.



<template>
  <div :class="classList">{{ letter }}</div>
</template>

<script lang="ts">
  export enum LetterSize {
    SM = 'sm',
    BASE = 'base',
    LG = 'lg',
    XL = 'xl',
  }
</script>

<script lang="ts" setup>
  import { computed } from 'vue';

  const props = defineProps({
    letter: {
      type: String,
      default: '',
    },
    size: {
      type: String as PropType<`${LetterSize}`>,
      default: LetterSize.BASE,
    },
  });

  const classList = computed(() => {
    const classes = {
      [LetterSize.SM]: ['w-[20px] h-[20px] text-[12px]'],
      [LetterSize.BASE]: ['w-[24px] h-[24px] text-[14px]'],
      // others
    };

    return classes[props.size];
  });
</script>


Enter fullscreen mode Exit fullscreen mode

There is a lot of code but let's discuss each part individually:

  1. In the template section, we have a div that will output the letter and computed class list based on size.
  2. In the first script section, we are declaring an enum for letter size
  3. In the second script section (setup), we are importing the utilities from vue, declaring component props, and creating a computed property to calculate the right size of the letter based on the prop.

Thanks to this approach, we could import both the component and the enum in another component like following:



  import Letter, { LetterSize } from '@/components/atoms/Letter.vue';


Enter fullscreen mode Exit fullscreen mode

And then use it in the template like so:



<Letter
  :size="LetterSize.XL"
  letter="X"
/>


Enter fullscreen mode Exit fullscreen mode

There might be also other cases when you may want to use this feature like:

  • Use the Options API to declare options that cannot be expressed in <script setup>, for example, inheritAttrs or custom options enabled via plugins.
  • Run side effects or create objects that should only execute once because setup() is run for every component.
  • Declare named exports which allow exporting multiple things from one file.

Read more about this feature here.

📖 Learn more

If you would like to learn more about Vue, Nuxt, JavaScript or other useful technologies, checkout VueSchool by clicking this link or by clicking the image below:

Vue School Link

It covers most important concepts while building modern Vue or Nuxt applications that can help you in your daily work or side projects 😉

✅ Summary

Well done! You have just learned how to use two script blocks in Vue Single File Components!

Take care and see you next time!

And happy coding as always 🖥️

Sentry blog image

Identify what makes your TTFB high so you can fix it

In the past few years in the web dev world, we’ve seen a significant push towards rendering our websites on the server. Doing so is better for SEO and performs better on low-powered devices, but one thing we had to sacrifice is TTFB.

Read more

Top comments (3)

Collapse
 
richardevcom profile image
richardevcom

While it is supported, it is strongly discouraged.

  • Do NOT use a separate <script> section for options that can already be defined using <script setup>, such as props and emits.

  • Variables created inside <script setup> are not added as properties to the component instance, making them inaccessible from the Options API. Mixing APIs in this way is strongly discouraged.

Collapse
 
gaundergod profile image
Gleb Kotovsky

In some cases, especially if you have own SSR in project (no nuxt and nuxt-bridge) exporting something from plain script can lead to unclear errors

Collapse
 
jacobandrewsky profile image
Jakub Andrzejewski

Hey there,

Thanks for sharing this! It might be easier for other to debug such issues after you have mentioned it :)

AWS Security LIVE!

Tune in for AWS Security LIVE!

Join AWS Security LIVE! for expert insights and actionable tips to protect your organization and keep security teams prepared.

Learn More

👋 Kindness is contagious

Immerse yourself in a wealth of knowledge with this piece, supported by the inclusive DEV Community—every developer, no matter where they are in their journey, is invited to contribute to our collective wisdom.

A simple “thank you” goes a long way—express your gratitude below in the comments!

Gathering insights enriches our journey on DEV and fortifies our community ties. Did you find this article valuable? Taking a moment to thank the author can have a significant impact.

Okay