JAVASCRIPT

Implementing Reusable Logic with a Custom Vue 3 Composable (useBatteryStatus)

Create a custom Vue 3 Composition API composable (`useBatteryStatus`) to encapsulate and reuse reactive logic for monitoring the device's battery status across components.

<!-- App.vue (Consuming the composable) -->
<template>
  <div>
    <h1>Device Battery Status</h1>
    <div v-if="isSupported">
      <p>Charging: {{ isCharging ? 'Yes' : 'No' }}</p>
      <p>Level: {{ Math.round(level * 100) }}%</p>
      <p>Charging Time: {{ chargingTime === Infinity ? 'N/A' : chargingTime + ' seconds' }}</p>
      <p>Discharging Time: {{ dischargingTime === Infinity ? 'N/A' : dischargingTime + ' seconds' }}</p>
    </div>
    <p v-else>Battery Status API not supported in this browser.</p>
  </div>
</template>

<script setup>
import { useBatteryStatus } from './composables/useBatteryStatus';

const { isSupported, isCharging, level, chargingTime, dischargingTime } = useBatteryStatus();
</script>

<!-- composables/useBatteryStatus.js (The custom composable) -->
import { ref, onMounted, onUnmounted } from 'vue';

export function useBatteryStatus() {
  const isSupported = ref('getBattery' in navigator);
  const isCharging = ref(false);
  const level = ref(1);
  const chargingTime = ref(0);
  const dischargingTime = ref(Infinity);
  let battery = null;

  const updateBatteryStatus = () => {
    if (!battery) return;
    isCharging.value = battery.charging;
    level.value = battery.level;
    chargingTime.value = battery.chargingTime;
    dischargingTime.value = battery.dischargingTime;
  };

  const initBattery = async () => {
    if (isSupported.value) {
      battery = await navigator.getBattery();
      updateBatteryStatus();

      battery.addEventListener('chargingchange', updateBatteryStatus);
      battery.addEventListener('levelchange', updateBatteryStatus);
      battery.addEventListener('chargingtimechange', updateBatteryStatus);
      battery.addEventListener('dischargingtimechange', updateBatteryStatus);
    }
  };

  onMounted(initBattery);

  onUnmounted(() => {
    if (battery) {
      battery.removeEventListener('chargingchange', updateBatteryStatus);
      battery.removeEventListener('levelchange', updateBatteryStatus);
      battery.removeEventListener('chargingtimechange', updateBatteryStatus);
      battery.removeEventListener('dischargingtimechange', updateBatteryStatus);
    }
  });

  return {
    isSupported,
    isCharging,
    level,
    chargingTime,
    dischargingTime,
  };
}
How it works: This snippet demonstrates creating and using a custom Vue 3 composable, `useBatteryStatus`, to encapsulate and reuse reactive logic for interacting with the Battery Status API. This composable exports reactive references (`ref`) for properties like `isCharging`, `level`, and `chargingTime`, allowing any component to easily monitor the device's battery status. It correctly handles mounting and unmounting to add and remove event listeners, preventing memory leaks and ensuring efficient resource management, a hallmark of well-designed composables.

Need help integrating this into your project?

Our team of expert developers can help you build your custom application from scratch.

Hire DigitalCodeLabs