TASIOMIND.DEV — OPERATIONAL▸▸▸FULL STACK DEVELOPER @ GWQ SERVICEPLUS AG▸▸▸FOUNDER — K8SGPT.AI▸▸▸OPEN SOURCE: ACTIVE▸▸▸DISTRIBUTED SYSTEMS / KUBERNETES / AI▸▸▸RUST + GO + PYTHON▸▸▸FIELD TESTED / STATUS — NOMINAL▸▸▸LOCATION: EUROPE/BERLIN▸▸▸TASIOMIND.DEV — OPERATIONAL▸▸▸FULL STACK DEVELOPER @ GWQ SERVICEPLUS AG▸▸▸FOUNDER — K8SGPT.AI▸▸▸OPEN SOURCE: ACTIVE▸▸▸DISTRIBUTED SYSTEMS / KUBERNETES / AI▸▸▸RUST + GO + PYTHON▸▸▸FIELD TESTED / STATUS — NOMINAL▸▸▸LOCATION: EUROPE/BERLIN▸▸▸

vue-do-dont

⛔️ Don’ts & ✅ Dos in Vue 3

1. ❌ Kein import * as Foo

Don't

code
import * as Utils from "@/utils";

Warum vermeiden?

  • Zieht das ganze Modul ins Bundle → kein Tree-Shaking
  • Schlechtere Lesbarkeit
  • Geringere IDE-Unterstützung

✅ Do

code
import { formatDate, parseInput } from "@/utils/date";

📚 Quelle: (Stack Overflow)(Stack Overflow).


2. ❌ Kein Store-Zugriff direkt in Komponenten

Don't

code
this.$store.dispatch("loadSomething"); // Options API Anti-Pattern

✅ Do

code
const { loadSomething } = useSomethingStore();
await loadSomething();

➡ Store-Zugriff nur über Composables in der App-Schicht!

📚 Quelle: (Codez Up)(Codez Up).


3. ❌ Kein $emit inline im Template

Don't

code
<button @click="$emit('save')">Speichern</button>

✅ Do

code
function onSave() {
  emit("save");
}
code
<button @click="onSave">Speichern</button>

📚 Quelle: (LearnVue)


4. ❌ Keine untypisierten Props/Refs

Don't

code
const isVisible = ref(false); // kein Typ

✅ Do

code
const isVisible = ref<boolean>(false);
code
const props = defineProps<{ title: string; isActive: boolean }>();

📚 Quelle: (Vue.js)(koderhq.com)


5. ❌ Kein any, lieber unknown

Don't

code
function parse(data: any) { ... }

✅ Do

code
function parse(data: unknown): ParsedData {
  if (typeof data === 'string') { ... }
}

📚 Quelle: (Stack Overflow)(thoughtbot).


6. ❌ Kein ungetesteter Zugriff auf .value

Don't

code
doSomething(thing.value.someProp);

✅ Do

code
if (thing.value) {
  doSomething(thing.value.someProp);
}

Oder mit Optional Chaining:

code
thing.value?.someProp;

📚 Quelle: (Stack Overflow)(Stack Overflow).


7. ❌ Kein v-if + v-for am gleichen Element

Don't

code
<li v-for="item in items" v-if="item.active">{{ item.name }}</li>

✅ Do

code
<template v-for="item in items">
  <li v-if="item.active">{{ item.name }}</li>
</template>

(Vue.js).

📚 Quelle: (Rish's Repository)


8. ❌ Kein :key="index"

Don't

code
<li v-for="(item, index) in list" :key="index">{{ item.name }}</li>

✅ Do

code
<li v-for="item in list" :key="item.id">{{ item.name }}</li>

📚 Quelle: (Vue School)


9. ❌ Keine komplexe Logik im Template

Don't

code
<span>{{ a && b ? format(c) : defaultValue }}</span>

✅ Do

code
const displayValue = computed(() => (a && b ? format(c) : defaultValue));
code
<span>{{ displayValue }}</span>

📚 Quelle: (DEV Community)


10. ❌ Keine globale Registrierung aller Komponenten

Don't

code
app.component("BaseButton", BaseButton); // global für jedes Element

✅ Do

code
import BaseButton from "@/components/BaseButton.vue";

Nur gezielt global registrieren, wenn wirklich überall benötigt (z. B. Layout-Komponenten).

📚 Quelle: (LearnVue)


11. ❌ Keine Side-Effects in computed()

Don't

code
const total = computed(() => {
  logTotal(); // side effect
  return price * quantity;
});

✅ Do

code
const total = computed(() => price * quantity);
watch(total, () => logTotal());

📚 Quelle: (Binarcode)


12. ❌ Props nicht mutieren

Don't

code
props.title = "Neuer Titel"; // ❌

✅ Do

code
const titleCopy = ref(props.title);
titleCopy.value = "Neuer Titel";

📚 Quelle: (Rish's Repository, Michael Thiessen)


13. ❌ Keine filters verwenden (Vue 2 Legacy)

Don't

code
{{ price | currency }}

✅ Do

code
const formattedPrice = computed(() => formatCurrency(price));
code
{{ formattedPrice }}

📚 Quelle: (Vue 3 Migration Guide)


14. ❌ Kein ungesicherter Einsatz von v-html

Don't

code
<div v-html="userInput"></div>

✅ Do

  • Nutze ein Sanitizer (z. B. DOMPurify)
  • Verwende besser Slots oder gerenderte Komponenten

📚 Quelle: (ESLint Vue)


15. ❌ Keine tiefen Watcher ohne Bedarf

Don't

code
watch(myObject, () => { ... }, { deep: true });

✅ Do

  • Nur verwenden, wenn wirklich nötig
  • Alternativ: spezifische Schlüssel beobachten

📚 Quelle: (diginode.in)


16. ❌ Keine globalen Mixins in Masse

Don't

code
app.mixin({ created() { ... } });

✅ Do

  • Nutze Composables
  • Lokale Mixins für spezifische Komponenten

📚 Quelle: (Codez Up)


17. ❌ Kein Event-Bus für globale Events

Don't

code
EventBus.$emit("user-logged-in");

✅ Do

  • Pinia, provide/inject, oder zentraler EventHandler verwenden

📚 Quelle: (tkacz.pro)


18. ❌ Kein Zugriff auf $parent

Don't

code
this.$parent.doSomething();

✅ Do

  • Verwende Props, Emits oder provide/inject

📚 Quelle: (DEV Community)


19. ❌ Keine Inline-Templates

Don't

code
export default {
  template: "<p>{{ message }}</p>",
};

✅ Do

  • Verwende .vue-SFCs (Single File Components)

📚 Quelle: (DEV Community)


20. ❌ Keine defineComponent ohne Typisierung

Don't

code
export default defineComponent({});

✅ Do

code
export default defineComponent({
  name: "MyComponent",
  props: {
    title: { type: String, required: true },
  },
});

Oder bei setup-only:

code
const props = defineProps<{ title: string }>();

➡ Immer explizite Typen für Props – für IDE, Autocomplete & Fehlervermeidung


21. ❌ Kein v-model ohne Namensgebung bei mehreren Props

Don't

code
<MyInput v-model="value" v-model="label" />

✅ Do

code
<MyInput v-model:value="value" v-model:label="label" />

➡ Immer benannte v-models bei mehreren Bindings


22. ❌ Kein direktes Einfügen von API- oder Store-Logik in Komponenten

Don't

code
const response = await axios.get("/users");

✅ Do

code
const { getUsers } = useUserApi();
const users = await getUsers();

➡ API-Zugriffe immer über Composables oder Services kapseln


23. ❌ Keine globale Nutzung von $t / $i18n ohne Fallbacks

Don't

code
$t("user.name");

✅ Do

code
const { t } = useI18n();
t("user.name", "Fallback Name");

➡ Lokale Instanz nutzen, Fallbacks immer mitdenken für Robustheit


24. ❌ Keine Logik in watchEffect, wenn nicht reaktiv notwendig

Don't

code
watchEffect(() => {
  if (data.value) fetchDetails();
});

✅ Do

code
watch(data, () => {
  fetchDetails();
});

watchEffect nur bei komplexen reaktiven Szenarien sinnvoll – ansonsten watch()


25. ❌ Kein ref(null) bei Objekten ohne Typ

Don't

code
const user = ref(null);

✅ Do

code
const user = ref<User | null>(null);

➡ Immer konkret typisieren, besonders bei Objekten & Arrays


26. ❌ Kein direktes Schreiben in Reactive-Objekte in Templates

Don't

code
<input v-model="user.name" />

➡ Falsch, wenn user aus defineProps() kommt!

✅ Do

code
const editableUser = ref({ ...props.user });
code
<input v-model="editableUser.value.name" />

Props dürfen nie direkt verändert werden


27. ❌ Kein wildes Verschachteln von v-if, v-for, v-show etc.

Don't

code
<div v-if="a">
  <div v-show="b">
    <ul v-for="item in items">
      ...
    </ul>
  </div>
</div>

✅ Do

Kapsle in Computed Properties oder eigene Subkomponenten

code
const shouldShowList = computed(() => a && b && items.length);
code
<template v-if="shouldShowList">
  <ItemList :items="items" />
</template>

➡ Mehr Klarheit, bessere Testbarkeit, bessere DX


28. ❌ Keine vermischte Nutzung von setup() und Options-API

Don't

code
export default {
  setup() {
    ...
  },
  data() {
    return { foo: true };
  }
};

✅ Do

→ Ganz oder gar nicht: entweder Composition API oder Options API

Exakt – !!entgeltschluessel.model.value ist die komprimierte, idiomatische Variante Hier ist der Do/Don't-Eintrag mit diesem Pattern eingebaut:


29. ❌ Kein überladener Vergleich auf "Wert vorhanden"

Don't

code
if (
  entgeltschluessel.model.value !== "" &&
  entgeltschluessel.model.value !== null &&
  entgeltschluessel.model.value !== undefined
) {
  // ...
}

✅ Do

code
if (!!entgeltschluessel.model.value) {
  // Wert ist truthy (nicht leer, null oder undefined)
}

➡ Noch klarer (wenn explizit erwartet wird, dass .value ein String ist):

code
const hasValue = !!entgeltschluessel.model.value?.trim();

🧠 Hinweis: !!foo ist idiomatisch für „hat einen gültigen Wert“ – aber: bei numerischen oder boolean-Werten kann 0 oder false fälschlich als „leer“ interpretiert werden.

Wenn das relevant ist (z. B. Zahl 0 ist gültig), dann lieber explizit prüfen:

code
if (entgeltschluessel.model.value !== null && entgeltschluessel.model.value !== undefined)

📚 Quelle:

„Um festzustellen, ob ein Wert in JavaScript wahr oder falsch ist, verwenden die doppelte Negation (!!value). Damit wird der Wert sauber und sicher in einen booleschen Wert umgewandelt.“ MDN Web Docs: Boolean coercion using !!


30. ⛔️ Keine Imports innerhalb von Funktionen

❌ Anti-Pattern

code
function fetchData() {
  const { useApi } = await import("@/composables/useApi");
  return useApi().getData();
}

✅ Do

code
import { useApi } from "@/composables/useApi";

function fetchData() {
  return useApi().getData();
}

➡ Dynamische Imports nur bei echter Lazy-Loading-Strategie in z. B. Router Guards oder Heavy Modules.

📚 Quelle: Vue Style Guide – Rule: Avoid Imports in Functions


31. 🔐 Zugriffsschutz über readonly()

Verwende readonly() für Props oder interne State-Weitergaben, um versehentliche Mutationen zu verhindern.

✅ Do

code
const readonlyUser = readonly(user);

➡ Readonly schützt z. B. Stores davor, außerhalb der Actions verändert zu werden.

📚 Quelle: Vue.js Guide – readonly()


32. 🧪 Hook-basierte Tests mit mountBuilder

Erstelle eigene Mount-Hilfsfunktionen für bessere Lesbarkeit & Testwiederverwendung:

code
function mountComponent(props: Partial<Props> = {}) {
  return mount(MyComponent, {
    props: { ...defaultProps, ...props },
  });
}

➡ Bessere DX, DRY-Tests, weniger Setup-Code

📚 Quelle: Vitest + Vue Testing Guide


33. 📥 Formular-Komponenten sind Controlled

Alle Form-Inputs sollten v-model mit modelValue verwenden und keine lokale Mutation durchführen.

✅ Struktur

code
defineProps<{ modelValue: string }>();
defineEmits<{ (e: "update:modelValue", value: string): void }>();

const onInput = (value: string) => emit("update:modelValue", value);

➡ Predictable State, bessere Testbarkeit, keine versteckten Nebeneffekte

📚 Quelle: Vue 3 Docs – Component v-model


34. ⚠️ watchEffect nur bei dynamischer Abhängigkeit

❌ Don't

code
watchEffect(() => {
  if (user.value) loadData();
});

✅ Do

code
watch(user, () => {
  loadData();
});

watchEffect() eignet sich nur bei nicht explizit benennbaren Abhängigkeiten.

📚 Quelle: Vue Docs – watch vs. watchEffect


35. ✨ Performance: Komponenten lazy laden

✅ Do (z. B. im Router)

code
{
  path: '/settings',
  component: () => import('@/views/SettingsView.vue'),
}

➡ Tree-Shaking, besseres Initial Loading, gute DX

📚 Quelle: Vue Router Docs – Lazy Loading


36. 🧼 Composables: Präfix useXyz beibehalten

Alle Composables folgen dem Namensschema useXyz, z. B.:

code
useAuth();
useFormValidation();
useKlinikFilter();

➡ Erhöht Lesbarkeit, IDE-Suche, Konsistenz im Projekt

📚 Quelle: VueUse & Community Guidelines


🧩 37. ❌ Kein unstrukturierter Component Output

❌ Don't

code
return {
  foo,
  bar,
  a,
  b,
  c,
};

✅ Do

code
return {
  foo,
  bar,
  nested: {
    a,
    b,
    c,
  },
};

➡ Verbesserte DX beim Destructuring im <template> oder bei Composition-Aufrufen.

📚 Quelle: Erfahrungswerte, Clean Code Patterns, DX-Optimierung


🔒 38. ❌ Kein direkter v-model auf store.state

❌ Don't

code
<input v-model="store.user.name" />

✅ Do

code
const name = ref(store.user.name);
watch(name, (newVal) => store.setName(newVal));

v-model verändert sofort Store-Daten → schwer rückverfolgbar & testbar.

📚 Quelle: Pinia Best Practices – Vue School