4👍
When using <script setup>
, the <component>.is
prop needs to be set to the component definition itself (not the component’s name).
One solution is to track the active index (instead of active tab component):
-
Change
activeTab
to be a computed prop that returns the current tab fromtabs[]
based on the active index. -
Create an
activeIndex
ref, initialized to0
. -
In the
v-for
, include theindex
iterator -
In the
button
‘sclick
handler, set theactiveIndex
to the currentindex
. -
In the
class
binding, compare the currentindex
toactiveIndex
.
<script setup>
import { onMounted, ref, computed } from 'vue'
const props = defineProps({
titles: {},
tabs: {},
})
1️⃣
const activeTab = computed(() => props.tabs[activeIndex.value])
2️⃣
const activeIndex = ref(0)
</script>
<template>
<div class="bg-white flex items-center rounded-tr rounded-tl shadow border-b border-grey overflow-hidden">
<button
3️⃣
v-for="(title, index) in titles"
4️⃣
@click="activeIndex = index"
v-text="title"
class="font-medium px-4 py-3 hover:bg-grey hover:bg-opacity-70 border-b-2 border-transparent hover:border-primary"
5️⃣
:class="index === activeIndex && 'text-red border-primary bg-grey bg-opacity-70 '"
/>
</div>
<div class="bg-white p-4 min-h-[calc(100vh-10rem)]">
<component :is="activeTab"></component>
</div>
</template>
Also, make sure to call markRaw()
on the component definitions in the binding to avoid the unnecessary overhead of reactivity. This also resolves a Vue warning about this in the browser console.
<template> 👇 👇
<Tab :titles="['Languages', 'Countries']" :tabs="[languages, countries]"> </Tab>
</template>
<script setup>
import { markRaw } from 'vue'
import Tab from '@/components/Tab.vue'
import Countries from '@/components/Countries.vue'
import Languages from '@/components/Languages.vue'
👇
const countries = markRaw(Countries)
const languages = markRaw(Languages)
</script>
- [Vuejs]-Vue.js Bundling to a single file
- [Vuejs]-Router view on Vue 3 doesn't catch event from child
Source:stackexchange.com