What's Actually Happening

Vue.js component is not appearing on the page. The component should render but nothing displays or errors appear.

The Error You'll See

javascript
// Console error:
[Vue warn]: Unknown custom element: <my-component> - did you register the component correctly?

Template compilation error:

bash
[Vue warn]: Error compiling template:

Component not found:

bash
Failed to mount component: template or render function not defined.

No output:

html
<!-- Component tag in DOM but no rendered content -->
<my-component></my-component>
<!-- Empty -->

Why This Happens

  1. 1.Component not registered - Missing local or global registration
  2. 2.Template syntax error - Invalid HTML or Vue template syntax
  3. 3.Wrong import path - Component file not found
  4. 4.Data not reactive - Properties added after initialization
  5. 5.v-if/v-show conditions - Condition preventing render
  6. 6.CSS hiding content - Styles hiding component

Step 1: Check Component Registration

```javascript // Vue 3 - Local registration:

// ChildComponent.vue export default { name: 'ChildComponent', template: '<div>Child</div>' }

// Parent.vue import ChildComponent from './ChildComponent.vue'

export default { components: { ChildComponent // Short for ChildComponent: ChildComponent }, template: '<ChildComponent />' }

// Vue 3 - Global registration: // main.js import { createApp } from 'vue' import App from './App.vue' import MyComponent from './MyComponent.vue'

const app = createApp(App) app.component('MyComponent', MyComponent) app.mount('#app')

// Vue 2 - Global registration: import Vue from 'vue' import MyComponent from './MyComponent.vue'

Vue.component('MyComponent', MyComponent) ```

Step 2: Verify Import Path

```javascript // Check file exists: // Wrong path: import MyComponent from './MyComponent' // Missing .vue

// Correct: import MyComponent from './MyComponent.vue'

// Check relative path: import MyComponent from '../components/MyComponent.vue'

// For TypeScript: import MyComponent from '@/components/MyComponent.vue' // With @ alias

// Check if file exports correctly: // MyComponent.vue export default { name: 'MyComponent' // Must have default export }

// Named export: export const MyComponent = { /* ... */ } // Import: import { MyComponent } from './MyComponent.vue' ```

Step 3: Check Template Syntax

```vue <template> <!-- Common errors: -->

<!-- Error: Multiple root elements (Vue 2) --> <div>One</div> <div>Two</div> <!-- Error in Vue 2 -->

<!-- Fix: Single root in Vue 2 --> <div> <div>One</div> <div>Two</div> </div>

<!-- Vue 3 supports multiple roots with fragments --> <div>One</div> <div>Two</div>

<!-- Error: Unclosed tags --> <div> <!-- Missing </div> -->

<!-- Error: Invalid v-for key --> <div v-for="item in items"> <!-- Missing :key -->

<!-- Fix: --> <div v-for="item in items" :key="item.id">

<!-- Error: Wrong v-model --> <input v-model="username"> <!-- username not in data -->

<!-- Fix: --> <input v-model="username"> <!-- username in data --> </template> ```

Step 4: Debug with Vue DevTools

```bash # Install Vue DevTools browser extension: # Chrome: https://chrome.google.com/webstore # Firefox: https://addons.mozilla.org

# Open DevTools -> Vue tab

# Check: # 1. Component appears in component tree # 2. Props values # 3. Data values # 4. Computed properties # 5. Events

# If component not in tree: # - Not mounted # - Registration issue # - Parent not rendering

# Check component state: # Click on component in tree # View all reactive data ```

Step 5: Check Reactivity Issues

```javascript // Vue 3 - Composition API: import { ref, reactive } from 'vue'

export default { setup() { // Reactive with ref: const count = ref(0)

// Reactive with reactive: const state = reactive({ name: 'Vue' })

return { count, state } } }

// Vue 2 - Reactivity pitfalls:

export default { data() { return { items: [] } }, mounted() { // BAD: Adding property after initialization this.newProperty = 'value' // Not reactive!

// FIX: Use Vue.set or this.$set this.$set(this, 'newProperty', 'value')

// Or define in data: data() { return { newProperty: null // Now reactive } }

// BAD: Array index assignment this.items[0] = 'new' // Not reactive!

// FIX: Use splice or $set this.$set(this.items, 0, 'new') // Or: this.items.splice(0, 1, 'new') } } ```

Step 6: Check v-if and v-show

```vue <template> <!-- v-if completely removes element from DOM --> <div v-if="showComponent"> This won't render if showComponent is false </div>

<!-- v-show just hides with CSS --> <div v-show="showComponent"> This renders but hidden with display: none </div>

<!-- Check condition --> <div v-if="items.length > 0"> Items: {{ items.length }} </div>

<!-- Debug condition --> <div>Condition value: {{ showComponent }}</div>

<!-- Common issue: async data --> <div v-if="user"> {{ user.name }} <!-- user is null initially --> </div>

<!-- FIX: Check if loaded --> <div v-if="user && user.name"> {{ user.name }} </div> </template>

<script> export default { data() { return { showComponent: true, // Check this value items: [], user: null // Will be loaded async } }, async mounted() { this.user = await fetchUser() } } </script> ```

Step 7: Check Props and Events

```vue <!-- Parent --> <template> <ChildComponent :title="pageTitle" @update="handleUpdate" /> </template>

<script> import ChildComponent from './ChildComponent.vue'

export default { components: { ChildComponent }, data() { return { pageTitle: 'Hello' } }, methods: { handleUpdate(value) { console.log('Updated:', value) } } } </script>

<!-- ChildComponent.vue --> <template> <div> <h1>{{ title }}</h1> <button @click="$emit('update', 'new value')">Update</button> </div> </template>

<script> export default { props: { title: { type: String, required: true } } } </script> ```

Step 8: Check CSS Issues

```vue <template> <!-- Content exists but hidden by CSS --> <div class="hidden-content"> This content might be hidden </div> </template>

<style> /* Check these issues: */

/* Display none */ .hidden-content { display: none; /* Content won't show */ }

/* Visibility hidden */ .hidden-content { visibility: hidden; /* Content takes space but invisible */ }

/* Opacity 0 */ .hidden-content { opacity: 0; /* Transparent but takes space */ }

/* Zero dimensions */ .hidden-content { height: 0; width: 0; overflow: hidden; /* Content clipped */ }

/* z-index issues */ .behind { z-index: -1; /* Behind other elements */ }

/* Position off screen */ .offscreen { position: absolute; left: -9999px; } </style>

<!-- Debug by adding visible styles temporarily --> <style> .debug { border: 2px solid red !important; background: yellow !important; } </style> ```

Step 9: Check Lifecycle Hooks

```javascript export default { data() { return { mounted: false, data: null } },

// Check these hooks for issues:

beforeCreate() { // Component initializing // Can't access this.data yet console.log('beforeCreate') },

created() { // Component created // Can access data, but not DOM console.log('created', this.data) },

beforeMount() { // Before DOM insertion console.log('beforeMount') },

mounted() { // DOM ready // Use this for DOM operations console.log('mounted', this.$el) this.mounted = true },

beforeUpdate() { // Before data change re-render console.log('beforeUpdate') },

updated() { // After re-render console.log('updated') },

beforeUnmount() { // Before component removed console.log('beforeUnmount') },

unmounted() { // Component removed console.log('unmounted') } } ```

Step 10: Vue.js Component Verification Script

```javascript // Add to component for debugging:

export default { name: 'MyComponent',

mounted() { console.log('=== Component Debug ===') console.log('Component mounted:', this.$options.name) console.log('Props:', this.$props) console.log('Data:', this.$data) console.log('Slots:', this.$slots) console.log('Attrs:', this.$attrs) console.log('Root element:', this.$el)

// Check if rendered if (this.$el) { console.log('Element HTML:', this.$el.outerHTML) } },

// Add error handler errorCaptured(err, vm, info) { console.error('Component error:', err) console.error('Component:', vm) console.error('Info:', info) return false } }

// Global error handler (main.js): app.config.errorHandler = (err, vm, info) => { console.error('Vue error:', err) console.error('Component:', vm) console.error('Info:', info) }

// Render function debug: render() { console.log('Rendering with state:', this.$data) return h('div', 'Content') } ```

Vue.js Component Checklist

CheckExpected
Component registeredListed in components
Import path correctFile exists
Template validNo compile errors
Props passedValues in DevTools
Data reactiveUpdates reflected
No CSS hidingElement visible

Verify the Fix

```javascript // After fixing component rendering

// 1. Check in DevTools // Vue tab shows component // Props and data correct

// 2. Console no errors // No Vue warnings

// 3. Element in DOM document.querySelector('my-component') // Returns element

// 4. Update triggers re-render // Change data, see update

// 5. Events work // Click handlers fire

// 6. Slots render // Transcluded content appears ```

  • [Fix React Component Not Rendering](/articles/fix-react-component-not-rendering)
  • [Fix Vue.js Props Undefined](/articles/fix-vuejs-props-undefined)
  • [Fix Angular Component Not Loading](/articles/fix-angular-component-not-loading)