DEV Community

Abdulnasır Olcan
Abdulnasır Olcan

Posted on

Vue Composition API Pattern (Vue 3.5 and Practical Use Cases) 🚀

Modern development requires dynamic, scalable, and maintainable code, especially when building modular applications. The Vue Composition API, introduced in Vue 3, offers an elegant way to handle state, reactivity, and logic encapsulation. With the release of Vue 3.5, new features and improved patterns have emerged to tackle more sophisticated use cases effectively.

This guide dives deep into Conditional Vue Composition API Patterns, featuring advanced examples, real-world scenarios, and cutting-edge techniques that make use of Vue 3.5 features. Both JavaScript and TypeScript implementations are provided to cater to different developer needs.

Why Use the Conditional Pattern?

The Conditional Composition API Pattern focuses on organizing and reusing logic based on specific conditions. It’s especially useful for scenarios like:

  • Dynamically changing UI based on user roles or preferences.
  • Fetching and caching data based on application states (e.g., tabs, modals).
  • Implementing feature toggles for A/B testing.

By encapsulating conditional logic, you can achieve:

  • Readability: Cleaner and more maintainable code.
  • Reusability: Composable logic shared across components.
  • Modularity: Decoupled logic for easier testing and scaling.

Core Setup with Vue Composition API

Before we explore advanced examples, let’s lay down the basics.

Simple Reactive Example (JavaScript)

<template>
  <div>
    <p>{{ message }}</p>
    <button @click="toggle">Toggle Message</button>
  </div>
</template>

<script>
import { ref } from 'vue';

export default {
  setup() {
    const message = ref('Hello, Vue!');
    const toggle = () => {
      message.value = message.value === 'Hello, Vue!' ? 'Goodbye, Vue!' : 'Hello, Vue!';
    };

    return { message, toggle };
  },
};
</script>
Enter fullscreen mode Exit fullscreen mode

Simple Reactive Example (TypeScript)

<template>
  <div>
    <p>{{ message }}</p>
    <button @click="toggle">Toggle Message</button>
  </div>
</template>

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

export default defineComponent({
  setup() {
    const message = ref<string>('Hello, Vue!');
    const toggle = (): void => {
      message.value = message.value === 'Hello, Vue!' ? 'Goodbye, Vue!' : 'Hello, Vue!';
    };

    return { message, toggle };
  },
});
</script>
Enter fullscreen mode Exit fullscreen mode

Advanced Conditional Patterns

1. Dynamic Form Handling with Schema-Based Validation

Scenario: A dynamic form builder where form fields change based on user preferences or roles.

Composable Example (JavaScript)

import { ref, computed } from 'vue';

export function useDynamicForm(role) {
  const formSchema = computed(() => {
    if (role.value === 'admin') {
      return [
        { label: 'Admin Code', type: 'text', required: true },
        { label: 'Permissions', type: 'checkbox', options: ['Read', 'Write'] },
      ];
    } else {
      return [
        { label: 'Name', type: 'text', required: true },
        { label: 'Email', type: 'email', required: true },
      ];
    }
  });

  const formData = ref({});

  return { formSchema, formData };
}
Enter fullscreen mode Exit fullscreen mode

Composable Example (TypeScript)

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

interface FormField {
  label: string;
  type: string;
  required?: boolean;
  options?: string[];
}

export function useDynamicForm(role: Ref<string>) {
  const formSchema = computed<FormField[]>(() => {
    if (role.value === 'admin') {
      return [
        { label: 'Admin Code', type: 'text', required: true },
        { label: 'Permissions', type: 'checkbox', options: ['Read', 'Write'] },
      ];
    } else {
      return [
        { label: 'Name', type: 'text', required: true },
        { label: 'Email', type: 'email', required: true },
      ];
    }
  });

  const formData = ref<Record<string, any>>({});

  return { formSchema, formData };
}
Enter fullscreen mode Exit fullscreen mode

2. Feature Toggles for A/B Testing

Scenario: Dynamically enabling or disabling features for different user groups.

Composable Example

import { ref } from 'vue';

export function useFeatureToggle() {
  const isFeatureEnabled = ref(false);

  const enableFeature = () => (isFeatureEnabled.value = true);
  const disableFeature = () => (isFeatureEnabled.value = false);

  return { isFeatureEnabled, enableFeature, disableFeature };
}
Enter fullscreen mode Exit fullscreen mode

Usage in Components

<template>
  <div>
    <p v-if="isFeatureEnabled">New Feature is Live!</p>
    <p v-else>Old Feature</p>
    <button @click="enableFeature">Enable Feature</button>
    <button @click="disableFeature">Disable Feature</button>
  </div>
</template>

<script>
import { useFeatureToggle } from '@/composables/useFeatureToggle';

export default {
  setup() {
    const { isFeatureEnabled, enableFeature, disableFeature } = useFeatureToggle();
    return { isFeatureEnabled, enableFeature, disableFeature };
  },
};
</script>
Enter fullscreen mode Exit fullscreen mode

3. Optimized Data Fetching with Vue 3.5 Suspense

Scenario: Data fetching with fallbacks and loading states using Suspense.

Component Example

<template>
  <Suspense>
    <template #default>
      <UserData />
    </template>
    <template #fallback>
      <p>Loading...</p>
    </template>
  </Suspense>
</template>

<script>
import { defineAsyncComponent } from 'vue';

const UserData = defineAsyncComponent(() =>
  import('@/components/UserData.vue')
);

export default {
  components: { UserData },
};
</script>
Enter fullscreen mode Exit fullscreen mode

Real-World Use Case: Multi-Tab Data Viewer

Scenario: Dynamic content loading for multi-tab dashboards.

Composable

import { ref, watch, Ref } from 'vue';
import axios from 'axios';

export function useTabData(tab: Ref<string>) {
  const data = ref<any>(null);
  const isLoading = ref<boolean>(false);

  const fetchData = async () => {
    isLoading.value = true;
    try {
      const response = await axios.get(`/api/tabs/${tab.value}`);
      data.value = response.data;
    } catch (error) {
      console.error(error);
    } finally {
      isLoading.value = false;
    }
  };

  watch(tab, fetchData, { immediate: true });

  return { data, isLoading };
}
Enter fullscreen mode Exit fullscreen mode

Component Usage

<template>
  <div>
    <select v-model="activeTab">
      <option value="tab1">Tab 1</option>
      <option value="tab2">Tab 2</option>
    </select>
    <div v-if="isLoading">Loading...</div>
    <div v-else>{{ data }}</div>
  </div>
</template>

<script>
import { ref } from 'vue';
import { useTabData } from '@/composables/useTabData';

export default {
  setup() {
    const activeTab = ref('tab1');
    const { data, isLoading } = useTabData(activeTab);

    return { activeTab, data, isLoading };
  },
};
</script>
Enter fullscreen mode Exit fullscreen mode

Conclusion

The Conditional Vue Composition API Pattern allows developers to create dynamic, reusable, and efficient logic that adapts to real-world complexities. By leveraging advanced techniques and features in Vue 3.5, you can:

  • Build modular, maintainable, and scalable applications.
  • Optimize performance with watch, Suspense, and computed.
  • Deliver enhanced user experiences tailored to specific conditions.

These patterns, combined with composable functions and TypeScript, provide a solid foundation for any modern Vue application.

Happy coding! 🚀

Top comments (1)

Collapse
 
philip_zhang_854092d88473 profile image
Philip

The Vue Composition API enables modular, scalable applications with dynamic and reusable logic, especially useful in scenarios like conditional UI changes and data fetching. Vue 3.5 introduces new features like Suspense and improved TypeScript support, enhancing performance and flexibility. EchoAPI can streamline API testing for these components, ensuring smooth integration and faster debugging for dynamic features like data fetching and feature toggles.