Clement Yuen
← Back to articles
Vue·Intermediate

Vue 3 Composition API: Designing Maintainable Components

10 Aug 2026 · 8 min read · Intermediate

  • #Vue
  • #CompositionAPI
  • #Architecture

Share

The Composition API is easy to start and easy to tangle. Maintainability comes from naming, extraction, and boundaries—not from using ref everywhere.

Prefer <script setup>

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

const props = defineProps<{ query: string }>();
const emit = defineEmits<{ select: [id: string] }>();

const open = ref(false);
const normalized = computed(() => props.query.trim().toLowerCase());
</script>

Typed props and emits keep component contracts readable for teammates.

Extract composables by capability

Name composables after behavior, not framework mechanics:

  • useProjectFilters
  • useInfiniteScroll
  • useClipboard

Avoid useStuff dumping grounds.

Typescript
import { computed, ref, type Ref } from 'vue';

export function useSearchFilter<T>(
  items: Ref<T[]>,
  predicate: (item: T, query: string) => boolean,
) {
  const query = ref('');
  const filtered = computed(() =>
    items.value.filter((item) => predicate(item, query.value)),
  );
  return { query, filtered };
}

State ownership

  • Local UI: ref / reactive in the component or composable
  • Cross-route client state: Pinia
  • Server state: fetch layer + cache policy (do not shove HTTP into every component)

Template discipline

Composition API does not excuse 400-line SFCs. Split when you have:

  • Multiple unrelated watch blocks
  • Distinct visual regions with their own state
  • Reused logic across pages

Conclusion

Treat composables as the Vue equivalent of well-named hooks: small, intentional, and easy to test without mounting the entire page.

Related Articles