સ્લોટ્સ (Slots)
આ પેજ ધારે છે કે તમે પહેલાથી જ કમ્પોનન્ટ્સના મૂળભૂત પાસાઓ વાંચી લીધું છે. જો તમે કમ્પોનન્ટ્સ માટે નવા હોવ તો પહેલા તે વાંચો.
સ્લોટ કન્ટેન્ટ અને આઉટલેટ (Slot Content and Outlet)
આપણે શીખ્યા છીએ કે ઘટકો પ્રોપ્સ સ્વીકારી શકે છે, જે કોઈપણ પ્રકારના JavaScript મૂલ્યો હોઈ શકે છે. પણ ટેમ્પલેટ કન્ટેન્ટ વિશે શું? કેટલાક કિસ્સાઓમાં, આપણે ચાઇલ્ડ કમ્પોનન્ટમાં ટેમ્પલેટ ફ્રેગમેન્ટ (fragment) પાસ કરવા માંગીએ છીએ, અને ચાઇલ્ડ કમ્પોનન્ટને તેના પોતાના ટેમ્પલેટમાં તે ફ્રેગમેન્ટ રેન્ડર કરવા દેવા માંગીએ છીએ.
ઉદાહરણ તરીકે, આપણી પાસે <FancyButton> ઘટક હોઈ શકે છે જે આના જેવા વપરાશને સમર્થન આપે છે:
template
<FancyButton>
મને ક્લિક કરો! <!-- સ્લોટ કન્ટેન્ટ -->
</FancyButton><FancyButton> નું ટેમ્પલેટ આના જેવું લાગે છે:
template
<button class="fancy-btn">
<slot></slot> <!-- સ્લોટ આઉટલેટ -->
</button><slot> એલિમેન્ટ એ સ્લોટ આઉટલેટ (slot outlet) છે જે સૂચવે છે કે પેરેન્ટ દ્વારા પૂરા પાડવામાં આવેલ સ્લોટ કન્ટેન્ટ (slot content) ક્યાં રેન્ડર થવું જોઈએ.

અને ફાઈનલ રેન્ડર થયેલ DOM:
html
<button class="fancy-btn">મને ક્લિક કરો!</button>સ્લોટ્સ સાથે, <FancyButton> બહારના <button> (અને તેની ફેન્સી સ્ટાઇલ) ને રેન્ડર કરવા માટે જવાબદાર છે, જ્યારે અંદરનું કન્ટેન્ટ પેરેન્ટ કમ્પોનન્ટ દ્વારા પૂરું પાડવામાં આવે છે.
સ્લોટ્સને સમજવાની બીજી રીત એ છે કે તેને JavaScript ફંક્શન્સ સાથે સરખાવવી:
js
// પેરેન્ટ કમ્પોનન્ટ સ્લોટ કન્ટેન્ટ પાસ કરી રહ્યું છે
FancyButton('મને ક્લિક કરો!')
// FancyButton તેના પોતાના ટેમ્પલેટમાં સ્લોટ કન્ટેન્ટ રેન્ડર કરે છે
function FancyButton(slotContent) {
return `<button class="fancy-btn">
${slotContent}
</button>`
}સ્લોટ કન્ટેન્ટ માત્ર લખાણ સુધી મર્યાદિત નથી. તે કોઈપણ માન્ય ટેમ્પલેટ કન્ટેન્ટ હોઈ શકે છે. ઉદાહરણ તરીકે, આપણે બહુવિધ એલિમેન્ટ્સ અથવા અન્ય ઘટકો પણ પાસ કરી શકીએ છીએ:
template
<FancyButton>
<span style="color:red">મને ક્લિક કરો!</span>
<AwesomeIcon name="plus" />
</FancyButton>સ્લોટ્સનો ઉપયોગ કરીને, અમારું <FancyButton> વધુ લવચીક અને પુનઃઉપયોગી છે. અમે હવે વિવિધ સ્થાનો પર વિવિધ આંતરિક કન્ટેન્ટ સાથે તેનો ઉપયોગ કરી શકીએ છીએ, પરંતુ બધું સમાન ફેન્સી સ્ટાઇલ સાથે હશે.
Vue કમ્પોનન્ટ્સની સ્લોટ મિકેનિઝમ નેટિવ વેબ કમ્પોનન્ટ <slot> એલિમેન્ટ થી પ્રેરિત છે, પરંતુ વધારાની ક્ષમતાઓ સાથે જે આપણે પછી જોઈશું.
રેન્ડર સ્કોપ (Render Scope)
સ્લોટ કન્ટેન્ટ પાસે પેરેન્ટ કમ્પોનન્ટના ડેટા સ્કોપની એક્સેસ હોય છે, કારણ કે તે પેરેન્ટમાં વ્યાખ્યાયિત થયેલ છે. ઉદાહરણ તરીકે:
template
<span>{{ message }}</span>
<FancyButton>{{ message }}</FancyButton>અહીં બંને {{ message }} ઇન્ટરપોલેશન્સ સમાન કન્ટેન્ટ રેન્ડર કરશે.
સ્લોટ કન્ટેન્ટ પાસે ચાઇલ્ડ કમ્પોનન્ટના ડેટાની એક્સેસ હોતી નથી. Vue ટેમ્પલેટ્સમાં એક્સપ્રેશન્સ ફક્ત તે સ્કોપને જ એક્સેસ કરી શકે છે જેમાં તે વ્યાખ્યાયિત થયેલ છે, જે JavaScript ના લેક્સિકલ સ્કોપિંગ (lexical scoping) સાથે સુસંગત છે. બીજા શબ્દોમાં:
પેરેન્ટ ટેમ્પલેટમાંના એક્સપ્રેશન્સ પાસે ફક્ત પેરેન્ટ સ્કોપની એક્સેસ હોય છે; ચાઇલ્ડ ટેમ્પલેટમાંના એક્સપ્રેશન્સ પાસે ફક્ત ચાઇલ્ડ સ્કોપની એક્સેસ હોય છે.
ફોલબેક કન્ટેન્ટ (Fallback Content)
એવા કિસ્સાઓ છે જ્યારે સ્લોટ માટે ફોલબેક (એટલે કે ડિફોલ્ટ) કન્ટેન્ટ સ્પષ્ટ કરવું ઉપયોગી છે, જે ત્યારે જ રેન્ડર કરવામાં આવે જ્યારે કોઈ કન્ટેન્ટ પૂરું પાડવામાં ન આવે. ઉદાહરણ તરીકે, <SubmitButton> કમ્પોનન્ટમાં:
template
<button type="submit">
<slot></slot>
</button>જો પેરેન્ટ કોઈ સ્લોટ કન્ટેન્ટ પૂરું પાડતું નથી, તો આપણે ઈચ્છીએ છીએ કે લખાણ "સબમિટ (Submit)" <button> ની અંદર રેન્ડર થાય. "સબમિટ" ને ફોલબેક કન્ટેન્ટ બનાવવા માટે, આપણે તેને <slot> ટેગ વચ્ચે મૂકી શકીએ છીએ:
template
<button type="submit">
<slot>
સબમિટ <!-- ફોલબેક કન્ટેન્ટ -->
</slot>
</button>હવે જ્યારે આપણે પેરેન્ટ કમ્પોનન્ટમાં <SubmitButton> નો ઉપયોગ કરીએ છીએ, ત્યારે સ્લોટ માટે કોઈ કન્ટેન્ટ પ્રદાન ન કરીએ તો:
template
<SubmitButton />આ ફોલબેક કન્ટેન્ટ, "સબમિટ" રેન્ડર કરશે:
html
<button type="submit">સબમિટ</button>પરંતુ જો આપણે કન્ટેન્ટ પ્રદાન કરીએ:
template
<SubmitButton>સેવ કરો</SubmitButton>પછી પૂરા પાડવામાં આવેલ કન્ટેન્ટ તેના બદલે રેન્ડર કરવામાં આવશે:
html
<button type="submit">સેવ કરો</button>નામવાળા સ્લોટ્સ (Named Slots)
એવા સમયે હોય છે જ્યારે સિંગલ કમ્પોનન્ટમાં બહુવિધ સ્લોટ આઉટલેટ્સ હોવા ઉપયોગી છે. ઉદાહરણ તરીકે, નીચેના ટેમ્પલેટ સાથે <BaseLayout> કમ્પોનન્ટમાં:
template
<div class="container">
<header>
<!-- આપણે હીડર કન્ટેન્ટ અહીં ઈચ્છીએ છીએ -->
</header>
<main>
<!-- આપણે મેઈન કન્ટેન્ટ અહીં ઈચ્છીએ છીએ -->
</main>
<footer>
<!-- આપણે ફૂટર કન્ટેન્ટ અહીં ઈચ્છીએ છીએ -->
</footer>
</div>આ કેસો માટે, <slot> એલિમેન્ટ પાસે એક વિશેષ એટ્રિબ્યુટ name છે, જેનો ઉપયોગ વિવિધ સ્લોટ્સને અનન્ય ID આપવા માટે થઈ શકે છે જેથી તમે નક્કી કરી શકો કે કન્ટેન્ટ ક્યાં રેન્ડર થવું જોઈએ:
template
<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>name વગરનું <slot> આઉટલેટ ગૌણ રીતે "default" નામ ધરાવે છે.
<BaseLayout> નો ઉપયોગ કરતા પેરેન્ટ કમ્પોનન્ટમાં, આપણે બહુવિધ સ્લોટ કન્ટેન્ટ ફ્રેગમેન્ટ્સ પાસ કરવાની રીતની જરૂર છે, દરેક એક અલગ સ્લોટ આઉટલેટને ટાર્ગેટ કરે છે. ત્યાં જ નામવાળા સ્લોટ્સ (named slots) આવે છે.
નામવાળા સ્લોટને પાસ કરવા માટે, આપણે v-slot ડાયરેક્ટિવ સાથે <template> એલિમેન્ટનો ઉપયોગ કરવાની જરૂર છે, અને પછી v-slot માં આર્ગ્યુમેન્ટ તરીકે સ્લોટનું નામ પાસ કરવું પડશે:
template
<BaseLayout>
<template v-slot:header>
<!-- હીડર સ્લોટ માટે કન્ટેન્ટ -->
</template>
</BaseLayout>v-slot પાસે ડેડિકેટેડ શોર્ટહેન્ડ # છે, તેથી <template v-slot:header> ને ટૂંકાવીને ફક્ત <template #header> કરી શકાય છે. તેને આ રીતે વિચારો "આ ટેમ્પલેટ ફ્રેગમેન્ટને ચાઇલ્ડ કમ્પોનન્ટના 'header' સ્લોટમાં રેન્ડર કરો".

શોર્ટહેન્ડ સિન્ટેક્સનો ઉપયોગ કરીને <BaseLayout> માં ત્રણેય સ્લોટ્સ માટે કન્ટેન્ટ પાસ કરતો કોડ અહીં છે:
template
<BaseLayout>
<template #header>
<h1>અહીં પેજ ટાઇટલ હોઈ શકે છે</h1>
</template>
<template #default>
<p>મેઈન કન્ટેન્ટ માટેનો પેરેગ્રાફ.</p>
<p>અને બીજો એક.</p>
</template>
<template #footer>
<p>અહીં કેટલીક સંપર્ક માહિતી છે</p>
</template>
</BaseLayout>જ્યારે કમ્પોનન્ટ ડિફોલ્ટ સ્લોટ અને નામવાળા સ્લોટ બંનેને સ્વીકારે છે, ત્યારે તમામ ટોપ-લેવલ નોન-<template> નોડ્સ ગૌણ રીતે ડિફોલ્ટ સ્લોટ માટે કન્ટેન્ટ તરીકે ગણવામાં આવે છે. તેથી ઉપરનાને આ પ્રમાણે પણ લખી શકાય છે:
template
<BaseLayout>
<template #header>
<h1>અહીં પેજ ટાઇટલ હોઈ શકે છે</h1>
</template>
<!-- ગૌણ (implicit) ડિફોલ્ટ સ્લોટ -->
<p>મેઈન કન્ટેન્ટ માટેનો પેરેગ્રાફ.</p>
<p>અને બીજો એક.</p>
<template #footer>
<p>અહીં કેટલીક સંપર્ક માહિતી છે</p>
</template>
</BaseLayout>હવે <template> એલિમેન્ટ્સની અંદરની દરેક વસ્તુ સંબંધિત સ્લોટ્સમાં પસાર કરવામાં આવશે. અંતિમ રેન્ડર કરાયેલ HTML આ પ્રમાણે હશે:
html
<div class="container">
<header>
<h1>અહીં પેજ ટાઇટલ હોઈ શકે છે</h1>
</header>
<main>
<p>મેઈન કન્ટેન્ટ માટેનો પેરેગ્રાફ.</p>
<p>અને બીજો એક.</p>
</main>
<footer>
<p>અહીં કેટલીક સંપર્ક માહિતી છે</p>
</footer>
</div>ફરીથી, તે તમને જાવાસ્ક્રિપ્ટ ફંક્શન સામ્યતાનો ઉપયોગ કરીને નામવાળા સ્લોટ્સને વધુ સારી રીતે સમજવામાં મદદ કરી શકે છે:
js
// વિવિધ નામો સાથે બહુવિધ સ્લોટ ફ્રેગમેન્ટ્સ પાસ કરવા
BaseLayout({
header: `...`,
default: `...`,
footer: `...`
})
// <BaseLayout> તેમને વિવિધ સ્થળોએ રેન્ડર કરે છે
function BaseLayout(slots) {
return `<div class="container">
<header>${slots.header}</header>
<main>${slots.default}</main>
<footer>${slots.footer}</footer>
</div>`
}શરતી સ્લોટ્સ (Conditional Slots)
ક્યારેક તમે સ્લોટમાં કન્ટેન્ટ પાસ કરવામાં આવ્યું છે કે નહીં તેના આધારે કંઈક રેન્ડર કરવા માંગો છો.
આ હાંસલ કરવા માટે તમે v-if સાથે સંયોજનમાં $slots પ્રોપર્ટીનો ઉપયોગ કરી શકો છો.
નીચેના ઉદાહરણમાં અમે ત્રણ શરતી સ્લોટ્સ સાથે 'કાર્ડ (Card)' કમ્પોનન્ટ વ્યાખ્યાયિત કરીએ છીએ: header, footer અને default. જ્યારે હીડર / ફૂટર / ડિફોલ્ટ માટે કન્ટેન્ટ હાજર હોય, ત્યારે અમે વધારાની સ્ટાઇલ પૂરી પાડવા માટે તેને લપેટવા (wrap) માંગીએ છીએ:
template
<template>
<div class="card">
<div v-if="$slots.header" class="card-header">
<slot name="header" />
</div>
<div v-if="$slots.default" class="card-content">
<slot />
</div>
<div v-if="$slots.footer" class="card-footer">
<slot name="footer" />
</div>
</div>
</template>ડાયનેમિક સ્લોટ નામો (Dynamic Slot Names)
ડાયનેમિક ડાયરેક્ટિવ આર્ગ્યુમેન્ટ્સ v-slot પર પણ કામ કરે છે, જે ડાયનેમિક સ્લોટ નામોની વ્યાખ્યા કરવાની મંજૂરી આપે છે:
template
<base-layout>
<template v-slot:[dynamicSlotName]>
...
</template>
<!-- શોર્ટહેન્ડ સાથે -->
<template #[dynamicSlotName]>
...
</template>
</base-layout>નોંધ કરો કે એક્સપ્રેશન ડાયનેમિક ડાયરેક્ટિવ આર્ગ્યુમેન્ટ્સના સિન્ટેક્સ અવરોધો (syntax constraints) ને આધીન છે.
સ્કોપ્ડ સ્લોટ્સ (Scoped Slots)
રેન્ડર સ્કોપ માં ચર્ચા કર્યા મુજબ, સ્લોટ કન્ટેન્ટ પાસે ચાઇલ્ડ કમ્પોનન્ટમાંના સ્ટેટની એક્સેસ હોતી નથી.
જો કે, એવા કિસ્સાઓ છે કે જેમાં જો સ્લોટનું કન્ટેન્ટ પેરેન્ટ સ્કોપ અને ચાઇલ્ડ સ્કોપ બંનેના ડેટાનો ઉપયોગ કરી શકે તો તે ઉપયોગી થઈ શકે છે. તે હાંસલ કરવા માટે, આપણે ચાઇલ્ડ માટે સ્લોટ રેન્ડર કરતી વખતે તેમાં ડેટા પાસ કરવાની રીતની જરૂર છે.
હકીકતમાં, આપણે બરાબર તે જ કરી શકીએ છીએ - આપણે સ્લોટ આઉટલેટમાં એટ્રિબ્યુટ્સ પાસ કરી શકીએ છીએ જેમ કે કમ્પોનન્ટમાં પ્રોપ્સ પાસ કરીએ છીએ:
template
<!-- <MyComponent> ટેમ્પલેટ -->
<div>
<slot :text="greetingMessage" :count="1"></slot>
</div>સિંગલ ડિફોલ્ટ સ્લોટ વિરુદ્ધ નામવાળા સ્લોટ્સનો ઉપયોગ કરતી વખતે સ્લોટ પ્રોપ્સ મેળવવાનું થોડું અલગ છે. અમે સૌ પ્રથમ ચાઇલ્ડ કમ્પોનન્ટ ટેગ પર સીધા v-slot નો ઉપયોગ કરીને, સિંગલ ડિફોલ્ટ સ્લોટનો ઉપયોગ કરીને પ્રોપ્સ કેવી રીતે મેળવવી તે બતાવવા જઈ રહ્યા છીએ:
template
<MyComponent v-slot="slotProps">
{{ slotProps.text }} {{ slotProps.count }}
</MyComponent>ચાઇલ્ડ દ્વારા સ્લોટમાં પાસ કરાયેલ પ્રોપ્સ સંબંધિત v-slot ડાયરેક્ટિવની વેલ્યુ તરીકે ઉપલબ્ધ છે, જે સ્લોટની અંદરના એક્સપ્રેશન્સ દ્વારા એક્સેસ કરી શકાય છે.
તમે સ્કોપ્ડ સ્લોટને ચાઇલ્ડ કમ્પોનન્ટમાં પસાર થતા ફંક્શન તરીકે વિચારી શકો છો. ચાઇલ્ડ કમ્પોનન્ટ પછી તેને કૉલ કરે છે, આર્ગ્યુમેન્ટ્સ તરીકે પ્રોપ્સ પાસ કરે છે:
js
MyComponent({
// ડિફોલ્ટ સ્લોટ પાસ કરવો, પણ એક ફંક્શન તરીકે
default: (slotProps) => {
return `${slotProps.text} ${slotProps.count}`
}
})
function MyComponent(slots) {
const greetingMessage = 'હેલો'
return `<div>${
// પ્રોપ્સ સાથે સ્લોટ ફંક્શનને કૉલ કરો!
slots.default({ text: greetingMessage, count: 1 })
}</div>`
}હકીકતમાં, આ સ્કોપ્ડ સ્લોટ્સ કેવી રીતે કમ્પાઇલ કરવામાં આવે છે અને તમે મેન્યુઅલ રેન્ડર ફંક્શન્સ (render functions) માં સ્કોપ્ડ સ્લોટ્સનો ઉપયોગ કેવી રીતે કરશો તેની ખૂબ નજીક છે.
નોંધ કરો કે v-slot="slotProps" સ્લોટ ફંક્શન સિગ્નેચર સાથે કેવી રીતે મેળ ખાય છે. બરાબર ફંક્શન આર્ગ્યુમેન્ટ્સની જેમ, આપણે v-slot માં ડિસ્ટ્રક્ચરિંગનો ઉપયોગ કરી શકીએ છીએ:
template
<MyComponent v-slot="{ text, count }">
{{ text }} {{ count }}
</MyComponent>નામવાળા સ્કોપ્ડ સ્લોટ્સ (Named Scoped Slots)
નામવાળા સ્કોપ્ડ સ્લોટ્સ સમાન રીતે કામ કરે છે - સ્લોટ પ્રોપ્સ v-slot ડાયરેક્ટિવની વેલ્યુ તરીકે એક્સેસિબલ હોય છે: v-slot:name="slotProps". શોર્ટહેન્ડનો ઉપયોગ કરતી વખતે, તે આના જેવું લાગે છે:
template
<MyComponent>
<template #header="headerProps">
{{ headerProps }}
</template>
<template #default="defaultProps">
{{ defaultProps }}
</template>
<template #footer="footerProps">
{{ footerProps }}
</template>
</MyComponent>નામવાળા સ્લોટમાં પ્રોપ્સ પાસ કરવી:
template
<slot name="header" message="હેલો"></slot>નોંધ કરો કે સ્લોટનું name પ્રોપ્સમાં શામેલ કરવામાં આવશે નહીં કારણ કે તે રિઝર્વ્ડ (reserved) છે - તેથી પરિણામી headerProps એ { message: 'હેલો' } હશે.
જો તમે ડિફોલ્ટ સ્કોપ્ડ સ્લોટ સાથે નામવાળા સ્લોટ્સ મિક્સ કરી રહ્યાં છો, તો તમારે ડિફોલ્ટ સ્લોટ માટે સ્પષ્ટ <template> ટેગનો ઉપયોગ કરવાની જરૂર છે. કમ્પોનન્ટ પર સીધા જ v-slot ડાયરેક્ટિવને મૂકવાનો પ્રયાસ કરવાથી કમ્પાઈલેશન એરર આવશે. આ ડિફોલ્ટ સ્લોટના પ્રોપ્સના સ્કોપ વિશેની કોઈપણ અસ્પષ્ટતાને ટાળવા માટે છે. ઉદાહરણ તરીકે:
template
<!-- <MyComponent> ટેમ્પલેટ -->
<div>
<slot :message="hello"></slot>
<slot name="footer" />
</div>template
<!-- આ ટેમ્પલેટ કમ્પાઇલ થશે નહીં -->
<MyComponent v-slot="{ message }">
<p>{{ message }}</p>
<template #footer>
<!-- message ડિફોલ્ટ સ્લોટનું છે, અને અહીં ઉપલબ્ધ નથી -->
<p>{{ message }}</p>
</template>
</MyComponent>ડિફોલ્ટ સ્લોટ માટે સ્પષ્ટ <template> ટેગનો ઉપયોગ કરવાથી તે સ્પષ્ટ કરવામાં મદદ મળે છે કે message પ્રોપ અન્ય સ્લોટની અંદર ઉપલબ્ધ નથી:
template
<MyComponent>
<!-- એક્સપ્લીસિટ (સ્પષ્ટ) ડિફોલ્ટ સ્લોટ વાપરો -->
<template #default="{ message }">
<p>{{ message }}</p>
</template>
<template #footer>
<p>અહીં કેટલીક સંપર્ક માહિતી છે</p>
</template>
</MyComponent>ફેન્સી લિસ્ટ ઉદાહરણ (Fancy List Example)
તમે કદાચ વિચારતા હશો કે સ્કોપ્ડ સ્લોટ્સ માટે કયો સારો ઉપયોગ હોઈ શકે. અહીં એક ઉદાહરણ છે: કલ્પના કરો કે એક <FancyList> કમ્પોનન્ટ જે વસ્તુઓની યાદી (લિસ્ટ) રેન્ડર કરે છે - તે રિમોટ ડેટા લોડ કરવા માટેના લોજિકને એન્કેપ્સ્યુલેટ કરી શકે છે, લિસ્ટ પ્રદર્શિત કરવા માટે ડેટાનો ઉપયોગ કરી શકે છે, અથવા પેજિનેશન (pagination) અથવા ઇન્ફિનાઇટ સ્ક્રોલીંગ (infinite scrolling) જેવી એડવાન્સ સુવિધાઓ પણ હોઈ શકે છે. જો કે, અમે ઈચ્છીએ છીએ કે તે દરેક આઈટમ કેવી દેખાય તેની સાથે લવચીક હોય અને દરેક આઈટમની સ્ટાઇલિંગ તેને વાપરનારા પેરેન્ટ કમ્પોનન્ટ પર છોડી દે. તેથી ઇચ્છિત વપરાશ આના જેવો દેખાઈ શકે છે:
template
<FancyList :api-url="url" :per-page="10">
<template #item="{ body, username, likes }">
<div class="item">
<p>{{ body }}</p>
<p>{{ username }} દ્વારા | {{ likes }} લાઈક્સ</p>
</div>
</template>
</FancyList><FancyList> ની અંદર, આપણે વિવિધ આઈટમ ડેટા સાથે સમાન <slot> ને બહુવિધ વખત રેન્ડર કરી શકીએ છીએ (નોંધ લો કે આપણે સ્લોટ પ્રોપ્સ તરીકે ઓબ્જેક્ટ પાસ કરવા માટે v-bind નો ઉપયોગ કરી રહ્યા છીએ):
template
<ul>
<li v-for="item in items">
<slot name="item" v-bind="item"></slot>
</li>
</ul>રેન્ડરલેસ કમ્પોનન્ટ્સ (Renderless Components)
અમે ઉપર જે <FancyList> ઉદાહરણની ચર્ચા કરી છે તે પુનઃઉપયોગી લોજિક (ડેટા ફેચિંગ, પેજિનેશન વગેરે) અને વિઝ્યુઅલ આઉટપુટ બંનેને એન્કેપ્સ્યુલેટ કરે છે, જ્યારે સ્કોપ્ડ સ્લોટ્સ દ્વારા વિઝ્યુઅલ આઉટપુટનો ભાગ કન્ઝ્યુમર કમ્પોનન્ટ (consumer component) ને સોંપે છે.
જો આપણે આ ખ્યાલને થોડો આગળ ધપાવીએ, તો આપણે એવા ઘટકો સાથે આવી શકીએ છીએ જે માત્ર લોજિકને જ એન્કેપ્સ્યુલેટ કરે છે અને પોતાની રીતે કંઈપણ રેન્ડર કરતા નથી - વિઝ્યુઅલ આઉટપુટ સ્કોપ્ડ સ્લોટ્સ સાથે સંપૂર્ણપણે કન્ઝ્યુમર કમ્પોનન્ટને સોંપવામાં આવે છે. આપણે આ પ્રકારના કમ્પોનન્ટને રેન્ડરલેસ કમ્પોનન્ટ (Renderless Component) કહીએ છીએ.
રેન્ડરલેસ કમ્પોનન્ટનું ઉદાહરણ એ હોઈ શકે છે જે માઉસની વર્તમાન સ્થિતિને ટ્રેક કરવાના લોજિકને એન્કેપ્સ્યુલેટ કરે છે:
template
<MouseTracker v-slot="{ x, y }">
માઉસ અત્યારે અહીં છે: {{ x }}, {{ y }}
</MouseTracker>રસપ્રદ પેટર્ન હોવા છતાં, રેન્ડરલેસ કમ્પોનન્ટ્સ સાથે જે કંઈ પ્રાપ્ત કરી શકાય છે તે મોટાભાગે Composition API સાથે વધુ અસરકારક રીતે પ્રાપ્ત કરી શકાય છે, વધારાના કમ્પોનન્ટ નેસ્ટિંગના ઓવરહેડ વગર. પાછળથી, આપણે જોઈશું કે આપણે કમ્પોઝેબલ (Composable) તરીકે સમાન માઉસ ટ્રેકિંગ કાર્યક્ષમતાને કેવી રીતે અમલમાં મૂકી શકીએ છીએ.
તેમ છતાં, સ્કોપ્ડ સ્લોટ્સ હજી પણ એવા કિસ્સાઓમાં ઉપયોગી છે જ્યાં આપણે લોજિકને એન્કેપ્સ્યુલેટ કરવાની અને વિઝ્યુઅલ આઉટપુટ કમ્પોઝ કરવાની જરૂર હોય, જેમ કે <FancyList> ઉદાહરણમાં.