In this article, we are going to describe how to successfully access slots and attributes while using the Composition API and Script setup syntax. The use of these features while writing components using the Options API was quite simple, as all context was available within the “this” scope, but since the introduction of the composition API and the script setup, things have changed slightly and this post is going to show you how to use this great features.

What are Slots and Attrs

As with every post, it is important to spend a few words to ensure that all readers are aware of what Slots and Attrs are and how they can be used within the Vue framework.

Slots in Vue js

We start by spending a few words on Slots. From a great article on the site slots are referred as:

Slots are a reserved space offered by vuejs to display content passed down from one component to another.

Slots are usually defined and used within the <template> block of the Vue single file components (SFC) as shown in the following example:


//Parent of button
    This is going to be placed where the slots are <bold>Also accept HTML and components</bold>

We are not going to cover in detail how to use slots, but it is enough to know that during your component development, you will be required at times to make your component more flexible, and slots are going to be the feature that you were looking for.

Slots are also referred as $slots, because this is the syntax used to access them into the component template.

Attrs in Vue 3

It is now time to spend a few words on what attributes are in Vue 3. I am actually emphasising the Vue version as Vue 3, because the Attribute object, also known as $attrs, has actually changed. If you are interested in learning more, you can read this article titled: Build Advanced Components in Vue 3 using $attrs.

The attribute property is an object that contains all the ids, classes, attributes, events and data of a component. Attributes are referred to in the main Vue documentation as Fallback attributes. This name refers to the fact that the $attrs includes all the “undefined” properties that a component may have.

Here is a quick example of the attribute object on a custom component:


  aria-label="A nice button"

//MyButton.vue Attribute object

  aria-label: "A nice button"
  class: "dark-button"
  data-cy: "button"
  disabled: "true"
  id: "the-button"
  onClick: $event => (_ctx.doSomething())
  undefinedProperty: "ops"

While the slot component is more aimed at an advanced use-case, the use of the attrs object is very common while developing Vue application.

Before we move forward, it is very important to mention that the attribute object is automatically assigned to the root element of a custom component. So in our example above all the parameters will be assigned to the <button> element.

How to access $attrs and $slot in the <template>

We start with the simple solution that is accessing these properties within the template of your component. This syntax is not actually changed and it has stayed the same since Vue 2.

Accessing these two objects within a component is done using the `$slots` and `$attrs` variables:

      class="[ 'the--slot-is-an-svg': $slots.default().type === 'svg' ]"

As the above example shows. Accessing the slots and further attribute is extremely simple and clean. It is important to realise that the use of $slots using its actual object declaration is not very common and it is just expected from an advanced component. If you want to learn more about slot you can read my article on slots.

How to access Slots and Attrs using the Composition API

Even if the syntax sugar to retrieve Slots and Attrs in Vue 3 has changed, accessing these parameters is still quite simple. In Vue 2 (or Vue 3 while using the options API) access to the component context was available within the this keyword. So slots and attrs were respectively this.$slots and this.attrs.

In the composition API we have lost access to the context to this. To access these objects in Vue 3, we will have to use the arguments available within the setup function. In fact, the context previously available within this is now being passed as the second argument of the setup method.

// Example using the context object
export default {
  setup(props, context) {
    console.log( context.slots );
    console.log( context.attrs );

//Example using onject destructuring
export default {
  setup(props, { slots, attrs }) {
    console.log( slots );
    console.log( attrs );

The main difference from the previous example is that the variables have dropped the $ in their name.

How to access Slots and Attrs using the script setup

We have reached the example of our article. So far we have covered both template and Composition API. It is time to complete by the post by also defining how to access these arguments while using the script setup.

Since moving to Vue 3, I have spent lots of time googling around how to do something in Vue 3 due to the small changes in syntax and the <script setup> is the most interesting of all as not only has lost access to the context provided in the this keyword, but it also lacks access to the setup function, preventing us to access to its argument.

Luckily for you, this does not mean that these methods are harder to access at all. In fact, the amazing Vue core team has defined some easy-to-use composables that provide us everything we need to use slots and attrs.

The composable that we are going to use are useSlots and useAttrs. This information is accessible in the script setup documentation. If we would replicate the above example with a <script setup> syntax sugar we would write the following code:

<script setup>
import { useSlots, useAttrs } from 'vue'

const slots = useSlots()
const attrs = useAttrs()


I have written this article to hopefully save you some time googling around. Luckily for us, even if things have changed from the previous version of Vue to the current, it is still pretty simple to access these component properties.

Before saying goodbye, I would like to ask you to leave a comment if this article was useful and provide any feedback that may help me make this more useful for future readers.

🤞 Don’t miss these tips!

No spam emails.. Pinky promise!