CN
Piotr Jura·
December 20, 2023

Vue 3 Cheat Sheet with Composition API

Let's take a look at some of the most common Vue 3 features and syntax. Keep in mind, this is not a comprehensive guide. Though, it should be enough to get you started with Vue 3 and Composition API.

I've got a course on Vue you might like:

Setting up with Vite

The first step is to create a new Vue project. The best way is to use Vite - popular swiss-knife tool for all things frontend. Start a Vue 3 project using Vite by running the following commands:

npm init vite@latest my-vue-project --template vue
cd my-vue-project
npm install
npm run dev

Vite offers a faster development experience with features like hot module replacement (when running locally, all changes you made will be reflected in the browser after save, without having to refresh!).

Single File Components with <script setup>

Vue 3 allows using the <script setup> syntax, a more concise way to write components.

<template>
  <div>{{ message }}</div>
</template>

<script setup>
  import { ref } from "vue";

  const message = ref("Hello Vue!");
</script>

<style>
  div {
    color: blue;
  }
</style>

In <script setup>, top-level bindings are automatically exposed to the template.

Template Syntax and Binding

Vue's template syntax integrates seamlessly with JavaScript.

Text Interpolation

Display reactive data:

<template>
  <div>{{ message }}</div>
</template>

<script setup>
  import { ref } from "vue";

  const message = ref("Hello Vue!");
</script>

Attribute Binding

Dynamically bind attributes:

<template>
  <img :src="imageSrc" />
</template>

<script setup>
  import { ref } from "vue";

  const imageSrc = ref("path/to/image.jpg");
</script>

Directives

v-if, v-else-if, v-else

Conditionally render elements:

<template>
  <div v-if="showTypeA">Type A</div>
  <div v-else-if="showTypeB">Type B</div>
  <div v-else>Type C</div>
</template>

<script setup>
  import { ref } from "vue";

  const showTypeA = ref(true);
  const showTypeB = ref(false);
</script>

v-for

Render a list of items:

<template>
  <ul>
    <li v-for="item in items" :key="item.id">{{ item.text }}</li>
  </ul>
</template>

<script setup>
  import { ref } from "vue";

  const items = ref([
    { id: 1, text: "Item 1" },
    { id: 2, text: "Item 2" },
  ]);
</script>

v-on (@ shorthand)

Listen to events:

<template>
  <button @click="greet">Greet</button>
</template>

<script setup>
  import { ref } from "vue";

  const greet = () => alert("Hello!");
</script>

v-model

Create two-way data bindings:

<template>
  <input v-model="message" />
</template>

<script setup>
  import { ref } from "vue";

  const message = ref("");
</script>

Class and Style Bindings

Apply dynamic styles and classes:

<template>
  <div :class="{ active: isActive, 'text-danger': hasError }"></div>
  <div :style="{ fontSize: fontSize + 'px' }"></div>
</template>

<script setup>
  import { ref } from "vue";

  const isActive = ref(true);
  const hasError = ref(false);
  const fontSize = ref(16);
</script>

Computed Properties and Watchers

Handle complex logic and respond to changes:

<script setup>
  import { ref, computed, watch } from "vue";

  const firstName = ref("John");
  const lastName = ref("Doe");
  const fullName = computed(() => `${firstName.value} ${lastName.value}`);

  watch(firstName, (newValue) => console.log(`First name changed to ${newValue}`));
</script>

Slots

Slots allow parent components to inject content into child components, offering flexibility and reusability.

Basic Slot

A child component with a slot:

<!-- ChildComponent.vue -->
<template>
  <div>
    <slot></slot>
  </div>
</template>

In the parent component, any content inside <ChildComponent> gets projected into the slot.

<!-- ParentComponent.vue -->
<template>
  <ChildComponent>
    <p>This will be displayed where the slot is.</p>
  </ChildComponent>
</template>

Named Slots

Child components can have multiple slots with different names.

<!-- ChildComponent.vue -->
<template>
  <div>
    <slot name="header"></slot>
    <slot name="footer"></slot>
  </div>
</template>

In the parent, specify which slot to render the content into:

<!-- ParentComponent.vue -->
<template>
  <ChildComponent>
    <template #header>
      <h1>Header content here</h1>
    </template>
    <template #footer>
      <p>Footer content here</p>
    </template>
  </ChildComponent>
</template>

Scoped Slots

Scoped slots allow child components to pass data back to parent components within a slot.

<!-- ChildComponent.vue -->
<template>
  <div>
    <slot :text="slotText"></slot>
  </div>
</template>

<script setup>
  import { ref } from "vue";

  const slotText = ref("Text from Child Component");
</script>

The parent can use this data:

<!-- ParentComponent.vue -->
<template>
  <ChildComponent>
    <template #default="{ text }">
      <p>{{ text }}</p>
    </template>
  </ChildComponent>
</template>

Here, the child component provides the text property, and the parent uses it within its slot template.