Vue v-show
v-show toggles an element's visibility using CSS display instead of adding or removing it from the DOM, making it well suited for content that toggles frequently.
What v-show Does
v-show always renders the element into the DOM. Instead of mounting and unmounting it like v-if, Vue simply toggles an inline style of display: none based on whether the bound expression is truthy or falsy. The element, and any component inside it, stays alive the whole time.
v-show vs v-if
The two directives look similar in templates but behave very differently underneath. v-if performs true conditional rendering — elements and their lifecycle hooks are created and destroyed on every switch. v-show mounts the element once and afterward only flips a CSS property, so lifecycle hooks like mounted() run a single time regardless of how many times visibility toggles.
- Prefer v-show for UI the user toggles often, like tabs, accordions, or modals opened repeatedly
- Prefer v-if for content that is conditional on something that rarely changes, such as a user role
- Prefer v-if when the condition being false should mean the content truly doesn't exist for accessibility or security purposes
- v-show has no v-else counterpart — you must write the inverse condition on a second element if needed
A basic v-show toggle
const app = Vue.createApp({
data() {
return {
isVisible: true
}
},
methods: {
toggle() {
this.isVisible = !this.isVisible
}
}
})
app.mount('#app')
<!-- template -->
<div id="app">
<button @click="toggle">Toggle message</button>
<p v-show="isVisible">This paragraph stays in the DOM.</p>
</div>Switching between tab panels
const app = Vue.createApp({
data() {
return {
activeTab: 'profile'
}
}
})
app.mount('#app')
<!-- template -->
<div id="app">
<button @click="activeTab = 'profile'">Profile</button>
<button @click="activeTab = 'settings'">Settings</button>
<div v-show="activeTab === 'profile'">Profile panel content</div>
<div v-show="activeTab === 'settings'">Settings panel content</div>
</div>v-show driven by a computed property
const app = Vue.createApp({
data() {
return {
cartItemCount: 0
}
},
computed: {
hasItems() {
return this.cartItemCount > 0
}
},
methods: {
addItem() {
this.cartItemCount++
}
}
})
app.mount('#app')
<!-- template -->
<div id="app">
<button @click="addItem">Add to cart</button>
<p v-show="hasItems">You have {{ cartItemCount }} item(s) in your cart.</p>
</div>Exercise: Vue v-show
What mechanism does v-show use to hide an element?