How to Pass Props in Vue 3 with Composition API

William Schulte
4 min readApr 23, 2022

--

In this article, we’ll be looking at how to pass props from parent to child components in Vue 3 with Composition API. We’ll accomplish this by building a basic Vue 3 interface with animation provided by TailwindCSS and the HeadlessUI library.

The project that we’ll build is centered around a button click in a parent component which will trigger a HeadlessUI animation event in a child component. A watcher property will watch for a change on the state of the passed-in prop before executing the animation sequence.

In addition to Tailwind CSS and HeadlessUI, we’ll also be using <script setup>, which is the recommended syntax for Composition API.

Let’s get started!

Project Setup

Let’s kick off a new Vue 3 Tailwind CSS + Vite build. Run the following in the terminal:

npm init vite my-tailwind-project
cd my-tailwind-project

Next, install and initialize Tailwind CSS in your new project:

npm install -D tailwindcss
npx tailwindcss init -p

Add the following to tailwind.config.js:

module.exports = {
content: [
"./index.html",
"./src/**/*.{vue,js,ts,jsx,tsx}",
],
theme: {
extend: {},
},
plugins: [],
}

Create a new index.css file in ./src and add the following:

@tailwind base;
@tailwind components;
@tailwind utilities;

Update main.js to import index.css:

import { createApp } from 'vue'
import App from './App.vue'
import './index.css'
createApp(App).mount('#app')

Install the @headlessui/vue in order to access the transition animation component:

npm install @headlessui/vue

Run the app:

npm run dev

Components

In App.vue, delete the existing code and add the following:

This will render the event click button in a Tailwind CSS navigation bar:

Create a new component called ChildComponent in ./src/components. Add the following code to render the HeadlessUI animation:

Back in App.vue, register ChildComponent:

import ChildComponent from './components/ChildComponent.vue'

Then, wrap ChildComponent in the <main> tags.

In <script setup> for App.vue, set the show variable to be reactive, with the initial value set to true. Enable the transition method (bound to the click event button) to toggle between true and false states for show:

Then, pass the show prop to the ChildComponent:

<ChildComponent :show="show" />

In <script setup> for ChildComponent.vue, set the state of isShowing in the TransitionRoot HeadlessUI component to true. Use defineProps to handle the passing of the show prop into ChildComponent. Deconstruct the prop using toRefs().

Then, inside the watch property, pass in show as the first parameter in order to “watch” for a change in the state of show after clicking the button. If a change is detected, the second parameter (the callback function) will then change the state of isShowing, resulting in the execution of the animation sequence.

Here are the completed Parent and Child components:

Parent (App.vue)

Child (ChildComponent.vue)

Bonus Feature

You probably noticed that the demo features randomly changing colors on the HeadlessUI animation. Here’s how to implement that feature if you’re interested!

In App.vue, add a color array inside <script setup>. Create a new variable called randomColor and make it reactive. Initialize randomColor. Inside the Transition function, use Math.floor and Math.random to randomize the array values. Assign the randomized colorArray to randomColor.value

Then, on the ChildComponent instance in App.vue, pass randomColor as a prop:

<ChildComponent :show="show" :randomColor="randomColor" />

In ChildComponent.vue, set the randomColor prop in defineProps, with the type set to String:

const props = defineProps({
show: Boolean,
randomColor: String
})

Finally, add :class=”randomColor” to the div inside TransitionRoot, in order to bind the randomColor prop as a class to the animated div.

And there it is! You’ve now learned how to pass props (while building a cool interface along the way)!

Here is the GitHub link to the project:

For more information on the tools used for this project, here are some links:

Also, this is the first technical writing project I’ve undertaken in nearly 3 years so any feedback on how to improve the code would be much appreciated!

Stay tuned for more content!

--

--

William Schulte

Mobile App Developer, Coding Educator, LDS, Retro-gamer 🎮