How to Use Script Setup in Vuejs?

Vue Script Setup is an upgrade to both Single File Composition and Composition API. Every VueJS development company uses this approach as it offers a concise and clean code structure which eventually helps in reducing the unnecessary boilerplate code in any Vue file or application. The goal of developers while using Script Setup is to make the application more efficient and for this, they use it along with other VueJS functionalities and helpers. In this blog, we will explore Script Setup and demonstrate its application in VueJS development.

1. What is Script Setup?

In the Vue app development ecosystem, <script setup> is known as a compile-time syntactic sugar that is used by VueJS developers for the composition of APIs inside the SFCs (Single File Components). With the help of this approach along with SFCs and Composition APIs makes the syntax of the application highly recommended. Script Setup comes with a lot of benefits over the normal <script> syntax. Below, we describe some of these advantages:

  • Vue Script Setup boosts runtime performance, enabling the application’s template to compile into a render function seamlessly, without the need for a proxy.
  • It offers props and emitted events with the use of TypeScript.
  • With the help of this approach, the developers get better IDE type-inference performance which means that the experts will have to spend less time for the language server to extract types from the application code.

2. How to Use Script Setup in Vuejs?

Here is how one can use script setup in VueJS:

2.1 Getting Started with Script Setup

The very first step to start using the Vue script setup in Vue is to opt-in to the syntax. For this, the developer will have to add the setup attribute to the <script> block of the application code as shown below:

<script setup>
console.log('Hello this is an example of script setup')
</script>

In the above code, we can see that the code inside is compiled component setup function’s content. This specifies that code written inside <Script setup> will get executed each time an instance is created for that component. This approach works opposite to normal <script>, which would have only executed the code once during the first import of the component.

2.2 Using Components

You can also use Vue script setup when working with Vue components. Here, the values present in the scope of <script setup> can directly be used as custom component names. Here is an example of the same:

<script setup>
import ExampleComponent from './ExampleComponent.vue'
</script>
<template>
  <ExampleComponent/>
</template>

The above code references MyComponent as a variable. In this case, if the developer has experience in working with JSX, the model of the code would be similar to that which will make it easy to use script setup in components. Basically, in this code, the kebab-case is similar to <my-component>.

When using Script Setup for components, developers can apply it differently across various types of components, including dynamic, recursive, and namespaced components. Here will have a look at each one of these: 

2.3 Dynamic Components

In using script setup in dynamic components, consider the components as variables rather than registered under string keys. This means that the developers can use dynamic:is binding while using dynamic components inside <script setup> as shown in the below code:

<script setup>
import Component1 from './Component1.vue'
import Component2 from './Component2.vue'
</script>
<template>
  <component :is="Component1"/>
  <component :is="condition ? Component1 : Component2"/>
</template>

To use components as variables, you must place them inside the ternary expression.

2.4 Recursive Components

When it comes to working with recursive components, the Single File Component (SFC) refers to itself with the use of a filename. For instance, if the name of the file is FooBar.vue, it can refer to itself as <FooBar/> in the application template. This approach tends to have a lower priority than imported components. Besides this, while working with this approach if the named import and the component’s inferred name conflict, the developer can alias the import as shown in the below code:

import { Component as MyComponent } from './components'

2.5 Namespaced Components

Namespaced components can also utilize script setup. There the developer will have to use the component tags along with dots. For instance, <Component>. This refers to components that are nested under the properties of an object. It can be used to import multiple components from one file. The code for the same is given below:

<script setup>
import * as Form from './form-components'
</script>
<template>
  <Form.Input>
    <Form.Label>Form Label</Form.Label>
  </Form.Input>
</template>

2.6 Reactivity

Reactivity stands out as another method to consider when utilizing script setup in Vue.js. Script setup utilizes the reactive state, which requires creating a state using Reactivity APIs. And here, just like the values are returned from a setup() function, refs are also automatically unwrapped when referenced in templates of the application. The code for the same is given below:

<script setup>
import { ref } from 'vue'
const counter = ref(0)
</script>
<template>
  <button @click="counter++">{{ counter }}</button>
</template>

2.7 Using Custom Directives

You can also use script setup with custom Vue directives. In general, when custom directives are globally registered with the use of script setup, they work normally but when it comes to locally registering the custom directives, <script setup> isn’t required. But having said that, for registering custom directives along with script setup, the naming scheme vNameOfDirective must be used as shown in the below line of commands:

<script setup>
const vMyCustomDirective = {
  beforeMount: (el) => {
    // do something with the element
  }
}
</script>
<template>
  <h1 v-my-custom-directive>This is a Heading</h1>
</template>

And when the developer wants to import the directive somewhere else, renaming it to fit the required naming scheme is possible using the following code:

<script setup>
import { myCustomDirective as vMyCustomDirective } from './MyCustomDirective.js'
</script>

2.8 defineProps

defineProps is a helper that is used by VueJs developers for defining props in the application code. This compile-time helper doesn’t require to be imported in the code as Vue will automatically understand that this helper is used when it compiles the application component. Here is how defineProps is used to return props in an application:

const props = defineProps({
  userModel: {
    type: Object as PropType<UserModel>,
    required: true
  },
  isWorking: {
    type: Boolean,
    default: false
  }
});

As seen in the above code of lines that defineProps enables receiving former props declaration in the form of a parameter. This can also be done using TypeScript for better results.

Comment
by from discussion
invuejs

When it comes to using defineProps, you can keep one thing in mind it is generically typed. This means that the developer can defineProps without a parameter, but will have to specify an interface as the props’ shape. Besides, the developers can also use TypeScript types, and add ? to specify the prop that isn’t required as shown by marking a prop as not required as shown in the below code:

const props = defineProps<{
  userModel: UserModel;
  isWorking?: boolean;
}>();

2.9 Defining Emits

defineEmits is a helper by Vue that enables the developers to return the emit function in the code. It works similarly to the defineProps helper as shown below: 

const emit = defineEmits({
  isSelected: () => true
});
Or even better, with TypeScript:
const emit = defineEmits<{
  (e: 'isSelected'): void;
}>();

It can also be written using TypeScript. Here, the below example shows how script setup syntax can be used with defineEmits helper to automatically expose everything to the template.

User.vue
<template>
  <figure @click="onClick()">
    <Image :src="userImageUrl" :alt="userModel.name"/>
    <figcaption>{{ userModel.name }}</figcaption>
  </figure>
</template>
<script setup lang="ts">
import { computed } from 'vue';
import Image from './Image.vue';
import { UserModel } from '@/models/UserModel';
interface Props {
  userModel: UserModel;
  isRunning?: boolean;
}
const props = withDefaults(defineProps<Props>(), { isRunning: false });
const emit = defineEmits<{
  (e: 'isSelected'): void;
}>();
const userImageUrl = computed(() => `/user-${props.userModel.color}${props.isWorking? '-working' : ''}.gif`);
function clicked() {
  emit('isSelected');
}
</script>

2.10 defineExpose

When script setup is used in components, they are closed by default which means that the public instance of the component that is supposed to be re-executed using $parent chains or template refs will not expose anything that is specified by the developer inside the script setup.

deineExpose is used to expose properties in a script setup component. And this is how it can be done:

<script setup>
import { ref } from 'vue'
const x = 10
const y = ref(20)
defineExpose({
  x,
  y
})
</script>

In the above code, we saw that when a parent component gets an instance of the defineExpose component through template refs, the instance that is re-executed will be displayed as { x: number, y: number }.

defineExpose

2.11 Using Slots and Attributes

Another approach where script setup can be used is in slots and attributes. Slots and attrs can be specified inside the script setup which is rare for some development concepts as one can directly access them as $slots and $attrs in the template. Here, useSlots and useAttrs helpers can be very beneficial to come out of this rare situation with the best results. An example of the same is given below:

<script setup>
import { useSlots, useAttrs } from 'vue'
const slots = useSlots()
const attributes = useAttrs()
</script>

As seen in the above code, useSlots and useAttrs are actual runtime functions. These functions help in return the equal value as setupContext.slots and setupContext.attrs.

2.12 Top-Level

The last approach in our list where script setup can be used is at the top level. Here, the top-level await can be specified inside the script setup. The code for the same is as shown below:

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

When the above code is run, the awaited expression automatically gets compiled in a format that holds the instance of the current component after the await.

2.13 Restrictions

There are some restrictions when it comes to using <script setup> and they are: 

  • Script Setup doesn’t support the In-DOM root component template. 
  • There is a difference in module execution semantics when it comes to using script setup which means that the code present inside <script setup> relies on the context of a Single File Component. 

3. Conclusion

As seen in this blog, Vue script setup is an amazing approach used by VueJS developers to get rid of the unnecessary wrapper in the application code along with some old component options. The minimal version of the Composition API considers it. Script Setup enables the developers to write their component logic using different concepts of Vue as described in this blog and can offer the best results.

FAQs

1. What is the Difference Between Setup and onMounted in Vue?

When it comes to Vue, the main difference between the setup and onMounted is that the setup() function is used by the developers when they want to declare a reactive data variable known as a counter with the use of the ref() Hook and also initialize the default value of it as zero. While on the other hand, the onMounted() hook is used for performing logic once the component has been mounted in the application code.

2. Can Lifecycle Hooks be Used Within the Script Setup?

Yes, developers can use the lifecycle hooks just like the onMounted hook directly within the script setup feature.

3. Are There Any Performance Benefits to Using Script Setup Over the Traditional Options API?

Yes, there are performance benefits to using the script setup feature and they are as below:

  • It offers better runtime performance.
  • With a script setup, you get an efficient approach to writing succinct code with less boilerplate.
  • The script setup syntax allows us to declare props and emitted events using TypeScript.
profile-image
Itesh Sharma

Itesh Sharma is core member of Sales Department at TatvaSoft. He has got more than 6 years of experience in handling the task related to Customer Management and Project Management. Apart from his profession he also has keen interest in sharing the insight on different methodologies of software development.

Comments

  • Leave a message...