Componentes
Los componentes de EmberKit son funciones simples que devuelven elementos JSX. Siguen el mismo modelo mental que React, pero con cero overhead de runtime por defecto.
Definir un componente
function Button({ children, variant = 'primary' }: { children: unknown; variant?: string }) {
return (
<button className={`btn btn-${variant}`}>
{children}
</button>
);
}
Los componentes reciben un único objeto de props y devuelven JSX. No hay componentes de clase, métodos de ciclo de vida ni enlace de this.
Usar componentes
function App() {
return (
<div>
<Button>Click me</Button>
<Button variant="secondary">Cancel</Button>
</div>
);
}
Children
Los componentes pueden aceptar children para actuar como contenedores:
function Card({ children, title }: { children: unknown; title: string }) {
return (
<div className="card">
<h3 className="card-title">{title}</h3>
<div className="card-body">{children}</div>
</div>
);
}
Renderizado condicional
Usa expresiones de JavaScript para la salida condicional:
function Status({ online }: { online: boolean }) {
return (
<div>
{online ? <span className="badge-green">Online</span> : <span className="badge-red">Offline</span>}
</div>
);
}
Listas
Usa map para renderizar listas con props key:
function TodoList({ items }: { items: string[] }) {
return (
<ul>
{items.map((item) => (
<li key={item}>{item}</li>
))}
</ul>
);
}
Estático vs interactivo
Concepto clave
Estático — sin handlers, sin data-ek-bind: HTML puro, sin JS en el cliente.
Interactivo — onClick / data-ek-bind: hidratación dirigida tras SSR.
function Title() {
return <h1>Hello</h1>;
}
function Counter() {
const [count, setCount] = createSignal(0);
return (
<div>
<button type="button" onClick={() => setCount((c) => c + 1)}>+</button>
<span data-ek-bind={count}>{count()}</span>
</div>
);
}
Detalles: Hidratación. Props signal en componentes: Signals.
Interfaz de props
Define los tipos de props con interfaces de TypeScript:
interface ButtonProps {
children: unknown;
variant?: 'primary' | 'secondary' | 'ghost';
size?: 'sm' | 'md' | 'lg';
disabled?: boolean;
onClick?: () => void;
}
function Button({ children, variant = 'primary', size = 'md', disabled, onClick }: ButtonProps) {
return (
<button
className={`btn btn-${variant} btn-${size}`}
disabled={disabled}
onClick={onClick}
>
{children}
</button>
);
}
Próximos pasos
- Routing — Routing basado en archivos
- Signals — Estado reactivo
- SSR y SSG — Modos de renderizado
- Context — Estado compartido entre componentes
- Internacionalización — Archivos JSON de traducción y rutas por locale