JAVASCRIPT
Create a Renderless Component for Reusable Logic in Vue 3
Develop a renderless component in Vue 3 to share complex logic and state without dictating UI, providing flexibility through scoped slots for custom rendering.
// components/ToggleVisibility.vue (Renderless Component)
<script>
import { ref } from 'vue';
export default {
name: 'ToggleVisibility',
setup(props, { slots }) {
const isVisible = ref(false);
const toggle = () => {
isVisible.value = !isVisible.value;
};
// Render the default slot and pass our logic and state as props
return () => slots.default({
isVisible: isVisible.value,
toggle: toggle
});
}
};
</script>
// src/App.vue
<template>
<div>
<h1>Renderless Component Example</h1>
<!-- Usage 1: Simple button to toggle text -->
<ToggleVisibility v-slot="{ isVisible, toggle }">
<button @click="toggle">
{{ isVisible ? 'Hide Text' : 'Show Text' }}
</button>
<p v-if="isVisible">This text is conditionally visible!</p>
</ToggleVisibility>
<hr />
<!-- Usage 2: Toggle image visibility -->
<ToggleVisibility v-slot="{ isVisible, toggle }">
<button @click="toggle">
{{ isVisible ? 'Hide Image' : 'Show Image' }}
</button>
<img v-if="isVisible" src="https://via.placeholder.com/150" alt="Placeholder" />
</ToggleVisibility>
</div>
</template>
<script setup>
import ToggleVisibility from './components/ToggleVisibility.vue';
</script>
How it works: A renderless component provides reusable logic and state without rendering any of its own HTML. In this example, `ToggleVisibility.vue` manages an `isVisible` state and a `toggle` method. Instead of a `<template>` block, its `setup` function directly returns a render function that invokes the default slot, passing `isVisible` and `toggle` as slot props. This allows the parent component (`App.vue`) to define its own UI (`<button>`, `<p>`, `<img>`) while leveraging the shared toggling logic from `ToggleVisibility`, promoting highly flexible and decoupled code.