Skip to content

EwVueComponent API

Overview

EwVueComponent is a powerful Vue 3 dynamic component wrapper that supports dynamic switching between multiple component types, including HTML tags, Vue components, async components, and component objects.

Basic Usage

vue
<!-- HTML tag -->
<EwVueComponent is="div" />

<!-- Vue component -->
<EwVueComponent :is="MyComponent" />

<!-- Component object -->
<EwVueComponent :is="componentObject" />

<!-- Async component -->
<EwVueComponent :is="asyncComponent" />

Props

is

  • Type: string | Component | ComponentObject | (() => Promise<Component>)
  • Required: Yes
  • Description: The component type to render
vue
<template>
  <!-- String component (HTML tag) -->
  <EwVueComponent is="div" />
  
  <!-- Vue component -->
  <EwVueComponent :is="MyComponent" />
  
  <!-- Component object -->
  <EwVueComponent :is="componentObject" />
  
  <!-- Async component -->
  <EwVueComponent :is="asyncComponent" />
</template>

<script setup>
import { ref } from 'vue'
import { EwVueComponent } from 'ew-vue-component'

// Vue component
const MyComponent = {
  name: 'MyComponent',
  template: '<div>Hello World</div>'
}

// Component object
const componentObject = {
  render() {
    return h('div', 'Hello from render function')
  }
}

// Async component
const asyncComponent = () => import('./MyAsyncComponent.vue')
</script>

fallback

  • Type: string | Component | ComponentObject
  • Default: undefined
  • Description: Fallback component to use when the main component fails to load
vue
<template>
  <EwVueComponent 
    :is="currentComponent"
    fallback="div"
  >
    <template #default>
      <p>Main content</p>
    </template>
  </EwVueComponent>
</template>

<script setup>
import { ref } from 'vue'
import { EwVueComponent } from 'ew-vue-component'

const currentComponent = ref('UnstableComponent')
</script>

errorComponent

  • Type: string | Component | ComponentObject
  • Default: undefined
  • Description: Custom error component
vue
<template>
  <EwVueComponent 
    :is="currentComponent"
    :error-component="ErrorComponent"
  />
</template>

<script setup>
import { ref, h } from 'vue'
import { EwVueComponent } from 'ew-vue-component'

const currentComponent = ref('BrokenComponent')

const ErrorComponent = {
  render() {
    return h('div', { class: 'error' }, [
      h('h3', 'Component Loading Failed'),
      h('p', 'Please try again later')
    ])
  }
}
</script>

cache

  • Type: boolean
  • Default: false
  • Description: Whether to enable component caching

cacheKey

  • Type: string
  • Default: ''
  • Description: Custom cache key

cacheTtl

  • Type: number
  • Default: 300000 (5 minutes)
  • Description: Cache time-to-live in milliseconds
vue
<template>
  <EwVueComponent 
    :is="currentComponent"
    :cache="true"
    cache-key="my-component"
    :cache-ttl="600000"
  />
</template>

plugins

  • Type: Plugin[]
  • Default: []
  • Description: Array of plugins to use
vue
<template>
  <EwVueComponent 
    :is="currentComponent"
    :plugins="[logPlugin, performancePlugin]"
  />
</template>

Props and Attrs Forwarding

EwVueComponent automatically forwards all props (except is, fallback, errorComponent, cache, cacheKey, cacheTtl, plugins) and attrs to the target component:

vue
<template>
  <EwVueComponent 
    :is="currentComponent"
    :title="title"
    :count="count"
    :disabled="disabled"
    class="my-component"
    data-testid="test-component"
    @click="handleClick"
    @input="handleInput"
  />
</template>

<script setup>
import { ref } from 'vue'
import { EwVueComponent } from 'ew-vue-component'

const currentComponent = ref('button')
const title = ref('Click me')
const count = ref(0)
const disabled = ref(false)

const handleClick = () => {
  count.value++
}

const handleInput = (value) => {
  console.log('Input:', value)
}
</script>

Slot Forwarding

EwVueComponent supports all types of slot forwarding:

vue
<template>
  <EwVueComponent :is="currentComponent">
    <!-- Default slot -->
    <template #default>
      <p>Default content</p>
    </template>
    
    <!-- Named slots -->
    <template #header>
      <h2>Header content</h2>
    </template>
    
    <!-- Scoped slots -->
    <template #item="{ data, index }">
      <div class="item">
        {{ index + 1 }}. {{ data.title }}
      </div>
    </template>
  </EwVueComponent>
</template>

<script setup>
import { ref } from 'vue'
import { EwVueComponent } from 'ew-vue-component'

const currentComponent = ref('ListItem')
</script>

Event Forwarding

All events are automatically forwarded to the target component:

vue
<template>
  <EwVueComponent 
    :is="currentComponent"
    @click="handleClick"
    @input="handleInput"
    @change="handleChange"
    @submit="handleSubmit"
  />
</template>

<script setup>
import { ref } from 'vue'
import { EwVueComponent } from 'ew-vue-component'

const currentComponent = ref('input')

const handleClick = (event) => {
  console.log('Click event:', event)
}

const handleInput = (event) => {
  console.log('Input event:', event.target.value)
}

const handleChange = (event) => {
  console.log('Change event:', event.target.value)
}

const handleSubmit = (event) => {
  console.log('Submit event:', event)
  event.preventDefault()
}
</script>

Events

error

  • Type: (error: Error) => void
  • Description: Triggered when component rendering encounters an error
vue
<template>
  <EwVueComponent 
    :is="currentComponent"
    @error="handleError"
  />
</template>

<script setup>
import { ref } from 'vue'
import { EwVueComponent } from 'ew-vue-component'

const currentComponent = ref('BrokenComponent')

const handleError = (error) => {
  console.error('Component error:', error)
  // Handle error here, such as showing error message, reporting error, etc.
}
</script>

Component Types

HTML Tags

vue
<template>
  <EwVueComponent is="div" class="container">
    <p>This is a div element</p>
  </EwVueComponent>
</template>

Vue Components

vue
<template>
  <EwVueComponent :is="MyComponent" :title="title" />
</template>

<script setup>
import { ref } from 'vue'
import { EwVueComponent } from 'ew-vue-component'
import MyComponent from './MyComponent.vue'

const title = ref('Hello World')
</script>

Component Objects

vue
<template>
  <EwVueComponent :is="componentObject" />
</template>

<script setup>
import { ref, h } from 'vue'
import { EwVueComponent } from 'ew-vue-component'

const componentObject = ref({
  render() {
    return h('div', { class: 'custom-component' }, 'Dynamically created component')
  }
})
</script>

Async Components

vue
<template>
  <EwVueComponent :is="asyncComponent" />
</template>

<script setup>
import { ref } from 'vue'
import { EwVueComponent } from 'ew-vue-component'

const asyncComponent = ref(() => import('./AsyncComponent.vue'))
</script>

Error Handling

Basic Error Handling

vue
<template>
  <EwVueComponent 
    :is="currentComponent"
    @error="handleError"
  />
</template>

<script setup>
import { ref } from 'vue'
import { EwVueComponent } from 'ew-vue-component'

const currentComponent = ref('BrokenComponent')

const handleError = (error) => {
  console.error('Component error:', error)
  // Fallback to safe component
  currentComponent.value = 'div'
}
</script>

Using Fallback Components

vue
<template>
  <EwVueComponent 
    :is="currentComponent"
    :fallback="FallbackComponent"
  />
</template>

<script setup>
import { ref, h } from 'vue'
import { EwVueComponent } from 'ew-vue-component'

const currentComponent = ref('BrokenComponent')

const FallbackComponent = {
  render() {
    return h('div', { class: 'fallback' }, 'Fallback content')
  }
}
</script>

Custom Error Components

vue
<template>
  <EwVueComponent 
    :is="currentComponent"
    :error-component="ErrorComponent"
  />
</template>

<script setup>
import { ref, h } from 'vue'
import { EwVueComponent } from 'ew-vue-component'

const currentComponent = ref('BrokenComponent')

const ErrorComponent = {
  props: ['error', 'retry'],
  render() {
    return h('div', { class: 'error-boundary' }, [
      h('h3', 'Something went wrong'),
      h('p', this.error?.message || 'Unknown error'),
      h('button', { onClick: this.retry }, 'Retry')
    ])
  }
}
</script>

Performance Features

Caching

vue
<template>
  <EwVueComponent 
    :is="currentComponent"
    :cache="true"
    :cache-key="cacheKey"
    :cache-ttl="600000"
  />
</template>

<script setup>
import { ref, computed } from 'vue'
import { EwVueComponent } from 'ew-vue-component'

const currentComponent = ref(() => import('./HeavyComponent.vue'))
const componentId = ref('heavy-1')

const cacheKey = computed(() => `heavy-component-${componentId.value}`)
</script>

Performance Monitoring

vue
<template>
  <EwVueComponent 
    :is="currentComponent"
    :plugins="[performancePlugin]"
  />
</template>

<script setup>
import { ref } from 'vue'
import { EwVueComponent } from 'ew-vue-component'

const currentComponent = ref('div')

const performancePlugin = {
  name: 'performance',
  beforeRender(component, props, context) {
    performance.mark('component-render-start')
  },
  afterRender(component, props, context) {
    performance.mark('component-render-end')
    performance.measure('component-render', 'component-render-start', 'component-render-end')
  }
}
</script>

TypeScript Support

EwVueComponent is fully written in TypeScript and provides complete type definitions:

typescript
import { EwVueComponent } from 'ew-vue-component'
import type { ComponentType, Plugin } from 'ew-vue-component'

// Type-safe component usage
const MyComponent: ComponentType = {
  render() {
    return h('div', 'Typed component')
  }
}

// Type-safe plugin
const myPlugin: Plugin = {
  name: 'my-plugin',
  beforeRender(component, props, context) {
    // Fully typed context
    context.utils.log('Rendering component')
  }
}

Released under the MIT License.