JAVASCRIPT
Reusable Renderless Component for Mouse Position Tracking in Vue 3
Implement a flexible renderless component in Vue 3 (Function as a Child Component pattern) to provide reusable logic like mouse tracking without UI constraints.
// components/MouseTracker.vue
<script>
import { ref, onMounted, onUnmounted, defineComponent } from 'vue';
export default defineComponent({
setup(_, { slots }) {
const x = ref(0);
const y = ref(0);
const update = (e) => {
x.value = e.pageX;
y.value = e.pageY;
};
onMounted(() => window.addEventListener('mousemove', update));
onUnmounted(() => window.removeEventListener('mousemove', update));
return () => slots.default ? slots.default({ mouseX: x.value, mouseY: y.value }) : null;
},
});
</script>
// src/App.vue
<template>
<div>
<h1>Track your mouse:</h1>
<MouseTracker v-slot="{ mouseX, mouseY }">
<p>Mouse X: {{ mouseX }}</p>
<p>Mouse Y: {{ mouseY }}</p>
</MouseTracker>
<hr />
<h2>Another usage:</h2>
<MouseTracker v-slot="{ mouseX, mouseY }">
<div :style="getDotStyle(mouseX, mouseY)" class="mouse-dot"></div>
</MouseTracker>
</div>
</template>
<script setup>
import MouseTracker from './components/MouseTracker.vue';
const getDotStyle = (x, y) => ({
transform: `translate(${x}px, ${y}px)`,
position: 'absolute',
left: '-10px',
top: '-10px',
});
</script>
<style scoped>
.mouse-dot {
width: 20px;
height: 20px;
background-color: #42b983;
border-radius: 50%;
pointer-events: none;
z-index: 9999;
}
</style>
How it works: This snippet demonstrates a renderless component pattern (Function as a Child Component, FaCC) in Vue 3. The `MouseTracker` component encapsulates the logic for tracking mouse coordinates (`x`, `y`) using reactive refs and event listeners. Instead of rendering its own UI, it exposes these reactive values via a scoped slot (`v-slot="{ mouseX, mouseY }"`). This allows consuming components to access the mouse data and render it in any desired way, promoting logic reuse and UI flexibility.