Exploring 10 Essential Vue.js Composables for Your Projects

In a Vue.js project, composables are functions used to reuse logic and state between different components. Here are some popular Vue.js composables that you can use in your project:

useLocalStorage and useSessionStorage

These composables help you store and manage data in the local storage or session storage of the browser.

<template>
  <div>
    <p>Last visited: {{ lastVisited }}</p>
  </div>
</template>

<script>
import { useLocalStorage } from '@vueuse/core';

export default {
  setup() {
    const lastVisited = useLocalStorage('last_visited', new Date());

    return {
      lastVisited,
    };
  },
};
</script>

useDebounce and useThrottle

These composables allow you to apply debounce or throttle to event handling functions, helping control the frequency of action execution.

<template>
  <div>
    <input v-model="searchQuery" @input="handleSearch" />
    <p>Search results: {{ searchResults }}</p>
  </div>
</template>

<script>
import { ref } from 'vue';
import { useDebounce } from '@vueuse/core';

export default {
  setup() {
    const searchQuery = ref('');
    const searchResults = ref([]);

    const handleSearch = useDebounce(() => {
      // Perform search based on searchQuery
      // Update searchResults
    }, 300);

    return {
      searchQuery,
      searchResults,
      handleSearch,
    };
  },
};
</script>

useMediaQueries

This composable helps you track media queries to perform responsive actions based on screen sizes.

<template>
  <div>
    <p>Current screen size: {{ screenSize }}</p>
  </div>
</template>

<script>
import { useMediaQueries } from '@vueuse/core';

export default {
  setup() {
    const { screenSize } = useMediaQueries({
      mobile: 'screen and (max-width: 640px)',
      tablet: 'screen and (max-width: 1024px)',
      desktop: 'screen and (min-width: 1025px)',
    });

    return {
      screenSize,
    };
  },
};
</script>

useAsync

This composable helps you manage asynchronous tasks and monitor their status (pending, success, error).

<template>
  <div>
    <button @click="fetchData">Fetch Data</button>
    <p v-if="status === 'pending'">Loading...</p>
    <p v-if="status === 'success'">Data loaded: {{ data }}</p>
    <p v-if="status === 'error'">Error loading data.</p>
  </div>
</template>

<script>
import { ref } from 'vue';
import { useAsync } from '@vueuse/core';

export default {
  setup() {
    const fetchData = async () => {
      // Simulate fetching data
      const response = await fetch('https://api.example.com/data');
      const data = await response.json();
      return data;
    };

    const { execute, value: data, status } = useAsync(fetchData);

    return {
      fetchData: execute,
      data,
      status,
    };
  },
};
</script>

useEventListener

This composable helps you track events on DOM elements and perform corresponding actions.

<template>
  <div>
    <p>Mouse position: {{ mouseX }}, {{ mouseY }}</p>
  </div>
</template>

<script>
import { ref } from 'vue';
import { useEventListener } from '@vueuse/core';

export default {
  setup() {
    const mouseX = ref(0);
    const mouseY = ref(0);

    useEventListener('mousemove', (event) => {
      mouseX.value = event.clientX;
      mouseY.value = event.clientY;
    });

    return {
      mouseX,
      mouseY,
    };
  },
};
</script>

useRouter

This composable helps you access router information and URL query parameters in a Vue Router application.

<template>
  <div>
    <p>Current route: {{ currentRoute }}</p>
  </div>
</template>

<script>
import { useRoute } from 'vue-router';

export default {
  setup() {
    const route = useRoute();
    const currentRoute = route.fullPath;

    return {
      currentRoute,
    };
  },
};
</script>

usePagination

This composable helps you manage paginated data display and navigation actions.

<template>
  <div>
    <ul>
      <li v-for="item in currentPageData" :key="item.id">{{ item.name }}</li>
    </ul>
    <button @click="previousPage" :disabled="currentPage === 1">Previous</button>
    <button @click="nextPage" :disabled="currentPage === totalPages">Next</button>
  </div>
</template>

<script>
import { ref, computed } from 'vue';
import { usePagination } from '@vueuse/core';

export default {
  setup() {
    const data = ref([...]); // Paginated data
    const itemsPerPage = 10;
    const currentPage = ref(1);

    const { currentPageData, nextPage, previousPage, totalPages } = usePagination(data, itemsPerPage, currentPage);

    return {
      currentPageData,
      nextPage,
      previousPage,
      currentPage,
      totalPages,
    };
  },
};
</script>

useIntersectionObserver

This composable helps you track the intersection of an element with the viewport, useful for performing actions when an element becomes visible or disappears.

<template>
  <div>
    <div ref="observedElement">Observed Element</div>
    <p v-if="isIntersecting">Element is intersecting!</p>
  </div>
</template>

<script>
import { ref } from 'vue';
import { useIntersectionObserver } from '@vueuse/core';

export default {
  setup() {
    const observedElement = ref(null);
    const { isIntersecting } = useIntersectionObserver(observedElement, {});

    return {
      observedElement,
      isIntersecting,
    };
  },
};
</script>

useClipboard

This composable helps you copy data to the clipboard and manage the copying state.

<template>
  <div>
    <p>Text to copy: {{ textToCopy }}</p>
    <button @click="copyText">Copy Text</button>
    <p v-if="copied">Copied to clipboard!</p>
  </div>
</template>

<script>
import { ref } from 'vue';
import { useClipboard } from '@vueuse/core';

export default {
  setup() {
    const textToCopy = ref('Hello, Vue.js!');
    const { copy, copied } = useClipboard();

    const copyText = () => {
      copy(textToCopy.value);
    };

    return {
      textToCopy,
      copyText,
      copied,
    };
  },
};
</script>

useRouteQuery

This composable helps you manage URL query state and update the page content based on URL queries.

<template>
  <div>
    <input v-model="searchQuery" />
    <button @click="updateQuery">Search</button>
    <p>Search results: {{ searchResults }}</p>
  </div>
</template>

<script>
import { ref } from 'vue';
import { useRouter, useRouteQuery } from '@vueuse/core';

export default {
  setup() {
    const router = useRouter();
    const searchQuery = ref('');
    const { search } = useRouteQuery();
    const searchResults = ref([]);

    const updateQuery = () => {
      router.push({ query: { search: searchQuery.value } });
      // Perform search based on searchQuery and update searchResults
    };

    return {
      searchQuery,
      searchResults,
      updateQuery,
    };
  },
};
</script>

Please note that to use these composables, you need to install the @vueuse/core library using npm or yarn. These composables help you reuse common logic and state in your Vue.js project, optimizing the development process and code management.