Chapter 54: Vue component Element

The <component> element (used almost exclusively with the :is attribute → <component :is=”…”>)

This is not a normal HTML tag — it’s a special placeholder that Vue provides so you can dynamically decide at runtime which real component (or even native HTML element) should be rendered at that spot in the template.

In plain words:

Instead of hard-coding <UserProfile /> or <ProductCard /> in your template, you write <component :is=”currentComponent” /> and then change the value of currentComponent whenever you want — based on tab selection, user role, route, permission, A/B test variant, data from server, etc.

It’s the Vue way of doing “dynamic component tag” — and it’s used in almost every medium or large Vue application in 2026.

Why <component :is> exists — real-life situations you will face

  1. Tabbed interfaces / dashboard widgets Different tabs need to show completely different components
  2. Role-based or permission-based UI Admin sees AdminDashboard, Editor sees EditorPanel, Guest sees ReadOnlyView
  3. Lazy-loading heavy / expensive components Only load ChartLibrary when user clicks “Analytics” tab
  4. Polymorphic / type-based rendering In a feed: render PostCard / StoryCard / AdCard / CommentCard based on item.type
  5. Wizard / multi-step forms Step 1 → PersonalInfoForm, Step 2 → PaymentDetails, Step 3 → Review
  6. CMS / page-builder style apps JSON from backend says “render HeroBanner component here, then FeatureGrid, then CTA”
  7. A/B testing or feature flags Show VariantA or VariantB component for 50% of users
  8. Dynamic content from server / config API returns which component should be used for this block

Basic Syntax – The canonical form

HTML

:is can receive:

  • A component definition (imported component object)
  • A string (component name — only if globally registered)
  • A dynamic import function (() => import(‘./SomeView.vue’))
  • null or undefined → nothing is rendered

Real, Complete, Production-Ready Example

Tabbed Dashboard with Lazy-Loading + KeepAlive

vue

Different Valid Ways to Use :is (All Common in 2026)

Style Code Example When to use it
Direct imported component import Profile from ‘./Profile.vue’ <component :is=”Profile” /> Small, always-used components
Async / lazy-loaded defineAsyncComponent(() => import(‘./HeavyChart.vue’)) Large bundles, route-based lazy loading
Object map / dictionary const views = { home: HomeView, profile: ProfileView } <component :is=”views[activeView]” /> Tabs, wizards, role-based views
String name (global registration) app.component(‘UserProfile’, UserProfile) <component is=”UserProfile” /> Rare in modern apps (local imports preferred)
Dynamic import from string (CMS) <component :is=”() => import(@/components/${block.type}.vue)” /> Headless CMS, page builders

Important Gotchas & Pro Tips (2026 Edition)

  • Always add :key when :is changes frequently

    vue

    → Prevents state leakage (form inputs, scroll position) when switching

  • Use <KeepAlive> to preserve state across switches

    vue

    → Tabs remember form data, scroll position, internal state — huge UX win

  • Loading & error handling for async components

    vue
  • SSR / hydration — sync components work fine, async ones are client-only

  • TypeScript — works beautifully

    TypeScript

Summary Table – When You Reach for <component :is>

Use Case Recommended :is Pattern Bonus Tip / Pattern
Tab / wizard navigation Map object + computed + <KeepAlive> + :key
Role/permission-based UI views[role] or ternary Combine with v-if for fallback
Lazy heavy components defineAsyncComponent(() => import(…)) + loading/error states
CMS / config-driven rendering Dynamic import from string Validate allowed component names
Polymorphic list items <component :is=”getComponentType(item)” /> Often inside v-for

Your Mini Practice After This Lesson

  1. Create 3 small tab components: Overview, Stats, Profile
  2. Build a tabbed interface using <component :is> + object map
  3. Add <KeepAlive> → switch tabs → see that form inputs / scroll position survive
  4. Add loading spinner for async tabs

Any part confusing? Want to see:

  • Dynamic components + <Transition> for smooth tab switch animations?
  • Real CMS-style rendering from JSON config?
  • Error boundary around async dynamic components?
  • Dynamic components inside v-for (polymorphic list items)?

Just tell me — we’ll build the next powerful dynamic example together 🚀

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *