Vue.js das progressive Framework für moderne UIs
Vue.js ist ein etabliertes JavaScript-Framework für interaktive Benutzeroberflächen und verbindet eine sanfte Lernkurve mit ausgereifter Reaktivität. Mit Vue 3, der Composition API und Composables schreiben wir Oberflächen, deren Logik wiederverwendbar und typsicher mit TypeScript bleibt, ergänzt um Pinia für globalen State und Vite für schnelle Builds. Wir entwickeln damit komplexe Web-Apps, Dashboards, Admin-Panels und E-Commerce-Frontends; kommen SEO oder Server-Side Rendering dazu, erweitern wir das Setup mit Nuxt. Das Ergebnis übergeben wir als dokumentierte, wiederverwendbare Vue-Komponenten, die Ihre Agentur unter eigenem Namen einsetzt.
01 / Einsatz
Wofür sich Vue.js eignet
- Komplexe Web-Apps
- Dashboard-Lösungen
- E-Commerce Frontends
- Admin-Panels
- Progressive Web Apps
02 / Einblick
Vue.js in der Praxis
Eine Suche. Drei Umsetzungen.
Dieselbe Suche in React, Vue und Svelte. Wechseln Sie zwischen den Codebeispielen und vergleichen Sie Zustände, Eingabebindung und die Ausgabe der Ergebnisse.
useState hält Eingabe und Ergebnis. useEffect startet die Suche; seine Aufräumfunktion beendet Timer und überholte Anfragen.
Passt, wenn bereits React-Komponenten vorhanden sind oder die Agentur ein React-Projekt weiterführen möchte.
Effekt-Abhängigkeiten und asynchrone Zustände brauchen klare Regeln. Für größere Anwendungen legen wir Datenabrufe und Fehlerbehandlung gemeinsam fest.
Code in React
'use client'
import { useEffect, useState } from 'react'
import { searchTopics, type Topic } from './search-source'
export function TopicSearch() {
const [query, setQuery] = useState('')
const [items, setItems] = useState<Topic[]>([])
const [loading, setLoading] = useState(true)
const [error, setError] = useState('')
useEffect(() => {
const controller = new AbortController()
setLoading(true)
setError('')
const timer = setTimeout(async () => {
try {
const results = await searchTopics(query, { signal: controller.signal })
if (!controller.signal.aborted) setItems(results)
} catch {
if (!controller.signal.aborted) setError('Die Suche ist nicht erreichbar.')
} finally {
if (!controller.signal.aborted) setLoading(false)
}
}, 250)
return () => { clearTimeout(timer); controller.abort() }
}, [query])
return <section>
<label>Thema suchen
<input value={query} onChange={event => setQuery(event.target.value)} />
</label>
<div role="status" aria-live="polite" aria-busy={loading}>
{loading ? <p>Suche läuft …</p> : error ? <p>{error}</p> :
items.length === 0 ? <p>Keine passenden Themen.</p> :
<ul>{items.map(item => <li key={item.id}>{item.title}</li>)}</ul>}
</div>
</section>
}ref hält die Werte. watch beobachtet die Eingabe und räumt über onCleanup die vorherige Suche auf. Das Template beschreibt die Zustände.
Passt zu vorhandenen Vue-Oberflächen und Teams, die mit Templates und der Composition API arbeiten.
Reaktivität ersetzt keine Anwendungsarchitektur. Datenfluss, gemeinsame Zustände und zusätzliche Bibliotheken müssen zum Projekt passen.
Code in Vue
<script setup lang="ts">
import { ref, watch } from 'vue'
import { searchTopics, type Topic } from './search-source'
const query = ref('')
const items = ref<Topic[]>([])
const loading = ref(true)
const error = ref('')
watch(query, (value, _, onCleanup) => {
const controller = new AbortController()
loading.value = true
error.value = ''
const timer = setTimeout(async () => {
try {
const results = await searchTopics(value, { signal: controller.signal })
if (!controller.signal.aborted) items.value = results
} catch {
if (!controller.signal.aborted) error.value = 'Die Suche ist nicht erreichbar.'
} finally {
if (!controller.signal.aborted) loading.value = false
}
}, 250)
onCleanup(() => { clearTimeout(timer); controller.abort() })
}, { immediate: true })
</script>
<template>
<section>
<label>Thema suchen <input v-model="query" /></label>
<div role="status" aria-live="polite" :aria-busy="loading">
<p v-if="loading">Suche läuft …</p>
<p v-else-if="error">{{ error }}</p>
<p v-else-if="items.length === 0">Keine passenden Themen.</p>
<ul v-else><li v-for="item in items" :key="item.id">{{ item.title }}</li></ul>
</div>
</section>
</template>$state hält die Werte. $effect erfasst die Eingabe als Abhängigkeit und gibt eine Aufräumfunktion für Timer und Anfrage zurück.
Passt zu eigenständigen Oberflächen und Werkzeugen, wenn die benötigten Integrationen verfügbar sind und das übernehmende Team Svelte kennt.
Benötigte Komponenten und Schnittstellen prüfen wir vor der Festlegung. Ein kurzer Komponentenquelltext belegt noch keine bessere Gesamtanwendung.
Code in Svelte
<script lang="ts">
import { searchTopics, type Topic } from './search-source'
let query = $state('')
let items = $state<Topic[]>([])
let loading = $state(true)
let error = $state('')
$effect(() => {
const value = query // Abhängigkeit vor dem asynchronen Abruf lesen
const controller = new AbortController()
loading = true
error = ''
const timer = setTimeout(async () => {
try {
const results = await searchTopics(value, { signal: controller.signal })
if (!controller.signal.aborted) items = results
} catch {
if (!controller.signal.aborted) error = 'Die Suche ist nicht erreichbar.'
} finally {
if (!controller.signal.aborted) loading = false
}
}, 250)
return () => { clearTimeout(timer); controller.abort() }
})
</script>
<section>
<label>Thema suchen <input bind:value={query} /></label>
<div role="status" aria-live="polite" aria-busy={loading}>
{#if loading}<p>Suche läuft …</p>
{:else if error}<p>{error}</p>
{:else if items.length === 0}<p>Keine passenden Themen.</p>
{:else}<ul>{#each items as item (item.id)}<li>{item.title}</li>{/each}</ul>
{/if}
</div>
</section>Rahmen des Beispiels und gemeinsame Datenquelle
Alle drei Beispiele verwenden dieselbe lokale Datenquelle search-source.ts. Nach einer kurzen Eingabepause startet die Suche. Eine neue Eingabe bricht die vorherige Anfrage ab. Ladezustand, leere Ergebnisse und Fehler gehören zur gleichen Aufgabe. Die gemeinsame Hilfsdatei steht unten; die Codeansicht oben zeigt die jeweilige Komponente.
export interface Topic {
id: string
title: string
category: string
}
const topics: Topic[] = [
{ id: 'design', title: 'Designsystem aufbauen', category: 'Gestaltung' },
{ id: 'cms', title: 'Inhalte mit einem CMS pflegen', category: 'Websites' },
{ id: 'api', title: 'Schnittstellen verbinden', category: 'Entwicklung' },
{
id: 'forms',
title: 'Formulare verständlich gestalten',
category: 'Gestaltung',
},
]
// Lokale Beispieldaten. Die Verzögerung macht Ladezustände sichtbar;
// sie misst nicht die Geschwindigkeit eines Frameworks.
export function searchTopics(
query: string,
{ signal, fail = false }: { signal: AbortSignal; fail?: boolean },
): Promise<Topic[]> {
return new Promise((resolve, reject) => {
if (signal.aborted) {
reject(new DOMException('Suche abgebrochen', 'AbortError'))
return
}
const cancel = () => {
clearTimeout(timer)
reject(new DOMException('Suche abgebrochen', 'AbortError'))
}
const timer = setTimeout(() => {
signal.removeEventListener('abort', cancel)
if (fail) {
reject(new Error('Die Suche ist gerade nicht erreichbar.'))
return
}
const term = query.trim().toLocaleLowerCase('de')
resolve(
topics.filter((topic) =>
`${topic.title} ${topic.category}`
.toLocaleLowerCase('de')
.includes(term),
),
)
}, 400)
signal.addEventListener('abort', cancel, { once: true })
})
}03 / Vorgehen
So arbeiten wir mit Vue.js
-
Projekt-Setup (Vite, Vue CLI)
-
Component-Architektur
-
State-Management (Pinia, Vuex)
-
Routing und Navigation
-
Performance-Optimierung (Lazy Loading, Code Splitting)
-
Testing und Deployment
Das liefern wir bei Vue.js
- Vue 3 Component-Library
- State-Management-Setup
- Routing-Konfiguration
- Performance-Optimierungen
- Component-Dokumentation
Häufige Fragen zu Vue.js
Warum Vue.js und nicht React?
Können Sie eine bestehende Vue 2-App auf Vue 3 migrieren?
Wann sollte ich Nuxt statt reinem Vue verwenden?
Wie strukturieren Sie größere Vue-Projekte?
Passende Leistungen
Vue.js für Ihr Projekt?
Beschreiben Sie uns Ihre Anforderungen. Wir besprechen, wie die Technologie in Ihr Projekt und Ihre vorhandene Infrastruktur passt.
Projekt besprechen