Tutorials Logic, IN +91 8092939553 info@tutorialslogic.com
FAQs Support
Navigation
Home About Us Contact Us Blogs FAQs
Tutorials
All Tutorials
Services
Academic Projects Resume Writing Interview Questions Website Development
Compiler Tutorials

Conditional Rendering

v-if vs v-show

Vue provides two ways to conditionally show elements. Choose based on how often the condition changes:

Featurev-ifv-show
DOM presenceRemoved/added from DOMAlways in DOM (display:none)
Initial render costLower (if false)Higher (always renders)
Toggle costHigher (destroy/create)Lower (CSS only)
Works with v-elseYesNo
Best forRarely toggled conditionsFrequently toggled visibility
v-if, v-else-if, v-else, v-show, Dynamic Components
<template>
  <div>
    <!-- v-if / v-else-if / v-else -->
    <div v-if="status === 'loading'">
      <span class="spinner"></span> Loading...
    </div>
    <div v-else-if="status === 'error'">
      <p class="error">{{ errorMessage }}</p>
      <button @click="retry">Retry</button>
    </div>
    <div v-else-if="status === 'empty'">
      <p>No data found.</p>
    </div>
    <div v-else>
      <!-- data is ready -->
      <ul>
        <li v-for="item in items" :key="item.id">{{ item.name }}</li>
      </ul>
    </div>

    <!-- v-show — stays in DOM, toggles display -->
    <div v-show="isMenuOpen" class="dropdown-menu">
      <a href="#">Profile</a>
      <a href="#">Settings</a>
      <a href="#">Logout</a>
    </div>
    <button @click="isMenuOpen = !isMenuOpen">Menu</button>

    <!-- <template> with v-if — no extra DOM element -->
    <template v-if="isAdmin">
      <h3>Admin Section</h3>
      <p>Only admins see this.</p>
      <button>Manage Users</button>
    </template>

    <!-- Conditional class/style -->
    <button
      :class="['btn', isActive ? 'btn-primary' : 'btn-secondary']"
      :disabled="isLoading"
    >
      {{ isLoading ? 'Saving...' : 'Save' }}
    </button>
  </div>
</template>

<script setup>
import { ref } from 'vue'

const status = ref('loading')  // 'loading' | 'error' | 'empty' | 'success'
const errorMessage = ref('Failed to fetch data')
const items = ref([{ id: 1, name: 'Item 1' }, { id: 2, name: 'Item 2' }])
const isMenuOpen = ref(false)
const isAdmin = ref(true)
const isActive = ref(true)
const isLoading = ref(false)

function retry() { status.value = 'loading' }
</script>
<!-- Dynamic Components — <component :is="..."> -->
<template>
  <div>
    <!-- Tab navigation -->
    <div class="tabs">
      <button
        v-for="tab in tabs"
        :key="tab.name"
        @click="currentTab = tab.name"
        :class="{ active: currentTab === tab.name }"
      >
        {{ tab.label }}
      </button>
    </div>

    <!-- Dynamic component — renders the active tab component -->
    <component :is="currentTabComponent" v-bind="tabProps" />

    <!-- KeepAlive — cache inactive components (preserve state) -->
    <KeepAlive :include="['HomeTab', 'ProfileTab']" :max="3">
      <component :is="currentTabComponent" />
    </KeepAlive>

    <!-- Dynamic component with string name (globally registered) -->
    <component :is="'BaseButton'" label="Click me" />

    <!-- Conditional component rendering -->
    <component
      :is="user.role === 'admin' ? AdminDashboard : UserDashboard"
      :user="user"
    />
  </div>
</template>

<script setup>
import { ref, computed } from 'vue'
import HomeTab    from './tabs/HomeTab.vue'
import ProfileTab from './tabs/ProfileTab.vue'
import SettingsTab from './tabs/SettingsTab.vue'
import AdminDashboard from './AdminDashboard.vue'
import UserDashboard  from './UserDashboard.vue'

const currentTab = ref('home')
const user = ref({ role: 'admin', name: 'Alice' })

const tabs = [
  { name: 'home',     label: 'Home',     component: HomeTab },
  { name: 'profile',  label: 'Profile',  component: ProfileTab },
  { name: 'settings', label: 'Settings', component: SettingsTab },
]

const currentTabComponent = computed(() =>
  tabs.find(t => t.name === currentTab.value)?.component
)

const tabProps = computed(() => ({
  userId: 1,
  // other shared props
}))
</script>

Ready to Level Up Your Skills?

Explore 500+ free tutorials across 20+ languages and frameworks.