DEV Community

Alex Spinov
Alex Spinov

Posted on

Vue 3 Has a Free API — Here's How to Build Reactive Apps with Composition API

Vue 3 introduces the Composition API — a flexible way to organize component logic. Combined with script setup and reactivity primitives, it makes building complex UIs intuitive.

Getting Started

npm create vue@latest my-app
cd my-app
npm install && npm run dev
Enter fullscreen mode Exit fullscreen mode

Composition API Basics

<script setup lang="ts">
import { ref, computed, onMounted } from "vue";

const count = ref(0);
const doubled = computed(() => count.value * 2);

function increment() {
  count.value++;
}

onMounted(() => {
  console.log("Component mounted!");
});
</script>

<template>
  <p>Count: {{ count }} (doubled: {{ doubled }})</p>
  <button @click="increment">+1</button>
</template>
Enter fullscreen mode Exit fullscreen mode

Reactive State

<script setup>
import { reactive, toRefs } from "vue";

const state = reactive({
  todos: [],
  filter: "all",
  newTodo: ""
});

const { todos, filter, newTodo } = toRefs(state);

function addTodo() {
  state.todos.push({ id: Date.now(), text: state.newTodo, done: false });
  state.newTodo = "";
}

const filteredTodos = computed(() => {
  if (state.filter === "done") return state.todos.filter(t => t.done);
  if (state.filter === "active") return state.todos.filter(t => !t.done);
  return state.todos;
});
</script>
Enter fullscreen mode Exit fullscreen mode

Composables (Custom Hooks)

// composables/useFetch.ts
import { ref, watchEffect } from "vue";

export function useFetch<T>(url: string) {
  const data = ref<T | null>(null);
  const error = ref<Error | null>(null);
  const loading = ref(true);

  watchEffect(async () => {
    loading.value = true;
    try {
      const res = await fetch(url);
      data.value = await res.json();
    } catch (e) {
      error.value = e as Error;
    } finally {
      loading.value = false;
    }
  });

  return { data, error, loading };
}

// Usage
const { data: users, loading } = useFetch<User[]>("/api/users");
Enter fullscreen mode Exit fullscreen mode

Props and Events

<script setup lang="ts">
const props = defineProps<{
  title: string;
  count?: number;
}>();

const emit = defineEmits<{
  (e: "update", value: number): void;
  (e: "delete"): void;
}>();
</script>
Enter fullscreen mode Exit fullscreen mode

Watchers

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

watch(count, (newVal, oldVal) => {
  console.log(`Changed from ${oldVal} to ${newVal}`);
});

watchEffect(() => {
  document.title = `Count: ${count.value}`;
});
</script>
Enter fullscreen mode Exit fullscreen mode

Need to extract or automate web content at scale? Check out my web scraping tools on Apify — no coding required. Or email me at spinov001@gmail.com for custom solutions.

Top comments (0)