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>
There is a lot of code but let's discuss each part individually:
- In the template section, we have a div that will output the letter and computed class list based on size.
- In the first script section, we are declaring an enum for letter size
- 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';
And then use it in the template like so:
<Letter
:size="LetterSize.XL"
letter="X"
/>
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 becausesetup()
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:
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 🖥️
Top comments (3)
While it is supported, it is strongly discouraged.
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
Hey there,
Thanks for sharing this! It might be easier for other to debug such issues after you have mentioned it :)