Components Guide
Defining a Component
ts
import { defineComponent, h } from 'nexa-framework'
const MyComponent = defineComponent({
setup(props, { emit, slots }) {
const count = signal(0)
return { count }
},
render(ctx) {
return h('div', null, [String(ctx.count.value)])
},
})Props and Emit
ts
defineComponent({
setup(props, { emit }) {
return {
submit: () => emit('submit', props.value)
}
},
render(ctx) {
return h('button', { onClick: ctx.submit }, ['Submit'])
},
})Slots
html
<!-- Child component -->
<template>
<div class="card">
<header>
<slot name="header" />
</header>
<main>
<slot />
</main>
</div>
</template>html
<!-- Parent component -->
<template>
<Card>
<template #header>
<h1>Title</h1>
</template>
<p>Default slot content</p>
</Card>
</template>Scoped Slots
html
<!-- Child passes data to slot -->
<template>
<ul>
<li v-for="item in items">
<slot :item="item" :index="index" />
</li>
</ul>
</template>Lifecycle Hooks
ts
import { onMounted, onBeforeUnmount, onUpdated } from 'nexa-framework'
setup() {
onMounted(() => console.log('mounted'))
onBeforeUnmount(() => console.log('cleanup'))
onUpdated(() => console.log('re-rendered'))
}v-show— togglesdisplayvia signalv-model— two-way binding for inputsv-if— conditional renderingv-for— list rendering
Event Modifiers
Nexa supports event modifiers to handle common event patterns efficiently:
.prevent— callsevent.preventDefault().stop— callsevent.stopPropagation().self— only triggers if the event was dispatched from the element itself (not a child)
html
<button @click.prevent="submit">Submit</button>
<div @click.self="closeModal">Click outside to close</div>Component Resolution
Nexa components should be named using PascalCase in templates to distinguish them from standard HTML elements. The compiler automatically resolves these names from the component's setup context.
html
<template>
<MyCustomButton>Click Me</MyCustomButton>
</template>
<script setup>
import MyCustomButton from './MyCustomButton.nexa'
</script>Transitions
Nexa provides enter/leave transitions via _enter and _leave props on any VNode:
ts
import { h, mount } from 'nexa-framework'
const vnode = h('div', {
_enter: 'fade', // apply 'fade-enter-*' classes on mount
_leave: 'fade', // apply 'fade-leave-*' classes on unmount
}, ['Hello'])Enter Animation
When a VNode with _enter is mounted:
{name}-enter-from+{name}-enter-activeclasses are applied immediately- On the next animation frame,
-enter-fromis removed and-enter-tois added - On
transitionend/animationend(or 300ms timeout), all enter classes are removed
Leave Animation
When a VNode with _leave is removed:
{name}-leave-from+{name}-leave-activeclasses are applied- DOM removal is deferred until the animation completes
- On the next frame,
-leave-fromis removed and-leave-tois added - On
transitionend/animationend(or 300ms timeout), the element is removed
CSS Example
css
.fade-enter-active, .fade-leave-active {
transition: opacity 0.3s ease;
}
.fade-enter-from, .fade-leave-to {
opacity: 0;
}Default Prefix
Pass true instead of a name to use the v- prefix:
ts
h('div', { _enter: true }, ['content'])
// uses v-enter-from, v-enter-active, etc.