Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In VueJS, Passing variable instead of string name of component to :is attribute of dynamic component does not work

In the code example below (referenced in VueJS Official Site) :

<script setup>
import Home from './Home.vue'
import Posts from './Posts.vue'
import Archive from './Archive.vue'
import { ref, watch } from 'vue'
 
let currentTab = ref('Home')

const tabs = {
  Home,
  Posts,
  Archive
}

watch(currentTab, (currentTab) => console.log(tabs[currentTab], currentTab))
</script>

<template>
  <div class="demo">
    <button
       v-for="(_, tab) in tabs"
       :key="tab"
       :class="['tab-button', { active: currentTab === tab }]"
       @click="currentTab = tab"
     >
      {{ tab }}
    </button>
      <component :is="tabs[currentTab]" class="tab"></component>
  </div>
</template>

<style>
.demo {
  font-family: sans-serif;
  border: 1px solid #eee;
  border-radius: 2px;
  padding: 20px 30px;
  margin-top: 1em;
  margin-bottom: 40px;
  user-select: none;
  overflow-x: auto;
}

.tab-button {
  padding: 6px 10px;
  border-top-left-radius: 3px;
  border-top-right-radius: 3px;
  border: 1px solid #ccc;
  cursor: pointer;
  background: #f0f0f0;
  margin-bottom: -1px;
  margin-right: -1px;
}
.tab-button:hover {
  background: #e0e0e0;
}
.tab-button.active {
  background: #e0e0e0;
}
.tab {
  border: 1px solid #ccc;
  padding: 10px;
}
</style>

taken from

Code Example

Code Example Reference on VueJS Official Page

... when i pass variable 'currentTab' to :is attribute (instead of tabs[currentTab], as below:

<component :is="currentTab" class="tab"></component>

... strangely the component stop showing, despite the fact value of variable 'currentTab' should resolve into the string value of a Component Name on which we click (like, 'Home', or 'Posts', or 'Archive' as you can see the value of variable that i display using console.log through "watch()" ).

So, the code works only when i pass "tabs[currentTab]" to :is attribute or when i pass the string name of the component (Home, or Posts, or Archive) as below:

<component :is="Archive" class="tab"></component> // shows only Archive OR <component :is="tabs[currentTab]" class="tab"></component> //Shows component w.r.t tab clicked.

If the variable 'currentTab' should resolve into its value to give:

<component :is="Archive" class="tab"></component> // shows only Archive

... then why there is strange behavior in resulting view ?

like image 333
Fakhar Anwar Avatar asked Sep 12 '25 08:09

Fakhar Anwar


1 Answers

In case of :is="Archive" and :is="tabs[currentTab]" the value is a component, while in case of :is="currentTab" it's a string.

It should either be used with a map of components like tabs, or resolved prior to usage:

let currentTabComp = computed(() => resolveComponent(currentTab.value))

This is not well-supported by script setup syntax, in order for this to work, the components need to be explicitly registered in component components option with regular script.

like image 90
Estus Flask Avatar answered Sep 15 '25 02:09

Estus Flask