Composition API vs Options API de Vue 3 para grandes bibliotecas de componentes
Composition API vs Options API en Vue 3: cómo cada estilo afecta la reutilización, las pruebas y el onboarding en grandes bibliotecas de componentes para paneles administrativos.

Por qué esta elección importa en grandes bibliotecas de componentes para administración
Una gran biblioteca de componentes en una aplicación de administración no es un sitio de marketing con unos pocos botones. Son docenas (o cientos) de bloques reutilizables que se repiten en pantallas: tablas de datos con ordenación y acciones masivas, paneles de filtros, formularios con reglas de validación, drawers y modales, flujos de confirmación y utilidades pequeñas como selectores de fecha y guards de permisos.
Porque estos patrones aparecen por todas partes, los equipos suelen copiar y ajustar código para cumplir plazos. Una tabla tiene una barra de filtros personalizada, otra tiene una ligeramente distinta, y pronto tienes cinco versiones “casi iguales”. Ahí es cuando la pregunta Composition API vs Options API deja de ser una preferencia personal y empieza a afectar la salud de toda la biblioteca.
Lo que suele romperse primero es la consistencia. La interfaz sigue funcionando, pero el comportamiento deriva: un modal se cierra con Escape en un sitio y en otro no; el mismo campo valida al perder el foco en una página y al enviar en otra. Después baja la velocidad porque cada cambio requiere buscar entre duplicados casi idénticos. Finalmente, baja la confianza: la gente evita refactorizaciones porque no puede predecir qué se verá afectado.
Tres decisiones prácticas importan más en una biblioteca compartida:
- Reutilización de código: cómo empaquetas la lógica compartida sin dependencias enredadas.
- Pruebas: qué tan fácil es verificar comportamientos sin tests frágiles y centrados en la UI.
- Onboarding: qué tan rápido un nuevo contribuyente puede leer un componente y hacer un cambio seguro.
Un ejemplo simple: tu admin tiene 20 páginas de listados y producto pide una nueva función de “Filtros guardados”. Si la lógica de la tabla, los filtros y la sincronización con la URL está dispersa e inconsistente, o lo lanzas lentamente o lo lanzas con errores. El estilo de API que elijas determina si esa lógica vive en un único lugar reutilizable, cuán claramente está conectada a cada pantalla y qué tan fácil es para alguien nuevo extenderla.
Si construyes aplicaciones administrativas en Vue 3 (incluyendo equipos que usan Vue 3 dentro de plataformas como AppMaster para la capa UI web), tomar esta decisión temprano puede ahorrar meses de mantenimiento más adelante.
Cómo difieren Options y Composition en el código del día a día
La forma más rápida de sentir la diferencia es abrir un componente grande de administración y preguntar: “¿Dónde cambio el comportamiento para esta característica?”. En una biblioteca de componentes, esa pregunta aparece a diario.
Con la Options API, el código se agrupa por tipo: data para estado, methods para acciones, computed para valores derivados y watch para efectos secundarios. Esa estructura es fácil de escanear cuando un componente es pequeño. En una tabla o formulario grande, la lógica de una sola característica (como acciones masivas o validación de campos) a menudo termina repartida en varios bloques. Puedes mantenerlo ordenado, pero requiere disciplina y nombres consistentes para evitar un flujo de trabajo de “saltar por el archivo”.
Con la Composition API, el código normalmente se agrupa por característica. Defines estado relacionado, valores derivados, efectos secundarios y helpers juntos, y puedes extraer lógica repetida en composables. En una biblioteca estilo admin, esto suele encajar con cómo piensa la gente: “todo lo relacionado con el filtrado está aquí”, “todo lo de la selección de filas está aquí”. También puede reducir duplicación entre componentes similares, por ejemplo reutilizando un composable usePagination en varias tablas.
Una gran diferencia cotidiana es cómo aparecen las dependencias.
- Options API puede sentirse más implícita: un método puede depender de
this.user,this.filtersythis.loading, y solo lo descubres leyendo dentro del método. - Composition API tiende a ser más explícita: cuando una función cierra sobre
filtersyloading, ves esas variables definidas cerca, y puedes pasarlas a funciones helper cuando haga falta.
El tradeoff es que Composition API puede volverse ruidosa si todo se tira dentro de un único setup() sin estructura.
Una regla práctica:
- Elige Options API cuando los componentes son mayormente presentacionales y tienen lógica ligera.
- Elige Composition API cuando los componentes tienen múltiples características con reglas compartidas en la biblioteca.
- Si eliges Composition API, acuerda una disposición simple que agrupe el código por característica (no “todos los refs primero”).
- Si eliges Options API, aplica nombres forzados y mantén la lógica relacionada junta con comentarios cortos y nombres de métodos consistentes.
Ambas pueden funcionar. La clave es elegir el estilo de organización que haga que el próximo cambio se sienta obvio, no ingenioso.
Reutilización de código: qué escala bien y qué se vuelve un desastre
En apps estilo admin, la reutilización no es algo opcional. Repites los mismos comportamientos en docenas de pantallas y pequeñas inconsistencias se convierten en errores y tickets de soporte.
La mayoría de necesidades de reutilización encajan en unos cuantos grupos recurrentes: ordenación/filtrado/paginación que coincida con el backend, validación de formularios y mapeo de errores, comprobaciones de permisos y gating de UI, sincronización de consultas (params de URL, vistas guardadas, filtros por defecto) y acciones masivas con reglas de selección en tablas.
Reutilización con Options API: potente, pero fácil de ocultar complejidad
Con Options API, la reutilización suele empezar con mixins, extends o plugins.
Los mixins son rápidos, pero escalan mal porque ocultan de dónde viene un método o un valor computado. Dos mixins pueden colisionar silenciosamente en el mismo nombre de método y entonces debugueas un comportamiento que no es visible en el archivo del componente.
extends puede sentirse más limpio que mixins, pero aún crea acertijos de herencia donde tienes que leer varios archivos para entender qué hace realmente un componente. Los plugins funcionan bien para preocupaciones a nivel de app (directivas globales, servicios compartidos), pero no son un buen lugar para reglas de negocio que varían por pantalla.
El momento en que todo se vuelve desordenado suele ser cuando la reutilización se vuelve implícita. Los nuevos contribuyentes no pueden responder “¿de dónde viene este dato?” sin buscar en todo el repositorio.
Reutilización con Composition API: composables que permanecen explícitos
La reutilización con Composition API suele basarse en composables: pequeñas funciones que retornan refs, valores computados y handlers. La gran ventaja es que la reutilización se vuelve visible cerca de la parte superior del componente y puedes pasar parámetros en lugar de depender de un contexto oculto del componente.
Por ejemplo, un composable usePagination puede aceptar valores por defecto y emitir cambios en una forma consistente, mientras que usePermissions puede aceptar el rol actual y el nombre de una funcionalidad. A ese punto, la elección deja de ser sintaxis y pasa a si tu biblioteca prefiere cableado explícito sobre herencia implícita.
Para mantener la reutilización predecible, trata cada unidad reutilizable como una mini-API: dale un nombre claro, define entradas y salidas, y una sola responsabilidad. Si un composable empieza a manejar paginación, caché, permisos y notificaciones, sepáralo. Es mucho más fácil intercambiar una pieza después sin romper todo lo demás.
Construir componentes de formulario y tabla reusables sin dolor
En apps estilo admin, formularios y tablas son donde una biblioteca de componentes o bien se paga o se convierte en un laberinto. Ambos APIs pueden funcionar. La diferencia es cómo empaquetas comportamientos compartidos como estado sucio, mapeo de errores y flujos de envío sin que cada componente parezca “especial”.
Para la lógica compartida de formularios, Options API suele empujarte hacia mixins o helpers compartidos. Los mixins pueden ser cómodos al principio, pero luego se complica responder preguntas básicas: “¿De dónde viene este error de campo?” o “¿Por qué el envío está deshabilitado?”.
Composition API hace este tipo de reutilización más visible porque puedes mover la lógica a composables (por ejemplo useDirtyState, useFormErrors, useSubmitFlow) y ver exactamente qué usa un componente de formulario. En una biblioteca grande, esa claridad suele importar más que ahorrar unas pocas líneas.
Una forma práctica de mantener estables las APIs de los componentes es tratar la superficie pública como un contrato: props, emits y slots deben cambiar raramente, aunque reescribas internals. Ese contrato luce igual en ambos estilos, pero Composition API frecuentemente hace los refactors más seguros porque puedes reemplazar un composable a la vez sin tocar la API del template.
Patrones que suelen mantenerse razonables conforme la biblioteca crece:
- Construye componentes base que hagan una sola tarea bien (BaseInput, BaseSelect, BaseTable), y luego complétalos en componentes de funcionalidad.
- Prefiere slots para flexibilidad de layout (área de acciones, estados vacíos, renderizado de celdas) en vez de agregar props para cada caso límite.
- Normaliza eventos temprano (por ejemplo
update:modelValue,submit,rowClick) para que las apps no dependan de detalles internos. - Mantén validación y formateo cerca de los inputs, pero deja las reglas de negocio afuera (en composables o contenedores parentales).
La sobreactracción es la trampa común. Un “super form” que maneja todo tipo de campos, toda regla de validación y cada opción de layout suele volverse más difícil de usar que Vue simple. Una buena regla: si un componente base necesita más que un puñado de props para cubrir las necesidades de todos los equipos, quizá son dos componentes.
A veces duplicar es la decisión correcta. Si solo una pantalla necesita un header de tabla raro con agrupación en varias filas, copia un pequeño fragmento y mantenlo local. Las abstracciones ingeniosas tienen una larga cola de mantenimiento, especialmente cuando nuevos contribuyentes tratan de entender la diferencia entre componentes “normales” y un framework dentro del framework.
Si decides entre Composition y Options para una gran biblioteca de formularios y tablas, optimiza primero por legibilidad del flujo de datos. La reutilización es genial, pero no cuando oculta el camino desde la acción del usuario hasta el evento emitido.
Impacto en las pruebas: qué es más fácil verificar
En una biblioteca de componentes, las pruebas suelen caer en tres grupos: lógica pura (formateo, validación, filtrado), renderizado (qué se muestra para un estado dado) e interacciones (clics, input, teclado, emits). El estilo de API que elijas cambia con qué frecuencia puedes probar el primer grupo sin montar un componente completo.
Las pruebas con Options API tienden a verse como “monta el componente, manipula el estado de la instancia, aserta el DOM”. Eso funciona, pero puede incentivar tests más grandes porque la lógica está mezclada en methods, computed, watch y hooks de ciclo de vida. Cuando falla algo, también pierdes tiempo averiguando si es temporización de watchers, un efecto del ciclo de vida o la lógica misma.
Options API suele parecer directa para:
- Flujos de usuario que dependen del orden de ciclo de vida (fetch en mount, reset en cambio de ruta).
- Comportamientos gobernados por watchers (auto-guardado, sincronización de query).
- Emisión de eventos desde métodos del componente (
save(),reset(),applyFilter()).
Composition API cambia el balance. Si mueves la lógica a composables, puedes testear esa lógica como funciones puras, con entradas pequeñas y salidas claras. Eso reduce la cantidad de pruebas “montar y clicar” necesarias y hace que las fallas sean más locales. También facilita controlar dependencias: en lugar de mockear un global, pasas la dependencia (una función de fetch, formateador de fechas o comprobador de permisos) al composable.
Un ejemplo concreto: una AdminTable reutilizable con ordenación, paginación y filas seleccionadas. Con Composition API, la lógica de selección puede vivir en useRowSelection() y probarse sin renderizar la tabla (toggle, limpiar, seleccionar todo, preservar entre páginas). Entonces mantienes un conjunto más pequeño de tests de componentes para confirmar que el template enlaza botones, checkboxes y eventos emitidos correctamente.
Para mantener las pruebas pequeñas y legibles (independientemente del estilo), construye una costura clara entre lógica y UI:
- Pon reglas de negocio en funciones puras o composables, no en watchers.
- Mantén efectos secundarios (fetch, storage, timers) detrás de dependencias inyectadas.
- Prefiere unas pocas pruebas de integración enfocadas por componente, no una prueba gigante de “todo”.
- Nombra estados y eventos de forma consistente en toda la biblioteca (reduce la configuración de tests).
- Evita acoplamientos ocultos (como el método A que depende de que el watcher B se ejecute).
Si tu objetivo es una decisión de estilo que mejore la estabilidad de las pruebas, inclínate hacia menos comportamientos gobernados por el ciclo de vida y más unidades lógicas aisladas que puedas verificar sin el DOM.
Incorporación de nuevos colaboradores: qué tan rápido son productivos
En una gran biblioteca de componentes estilo admin, el onboarding trata menos de enseñar Vue y más de ayudar a la gente a encontrar cosas, seguir convenciones y sentirse segura haciendo cambios. La mayoría de las ralentizaciones vienen de tres brechas: navegación (¿dónde está la lógica?), convenciones (¿cómo lo hacemos aquí?) y confianza (¿cómo cambio esto sin romper cinco pantallas?).
Con Options API, los recién llegados suelen avanzar más rápido el primer día porque la estructura es familiar: props, data, computed, methods, watchers. El costo es que el comportamiento real a menudo está disperso. Una sola característica como “filtrado server-side” puede estar dividida entre un watcher, un computed y dos métodos, más un mixin. La gente puede leer cada bloque, pero pasa tiempo hilando la historia.
Con Composition API, la ventaja de onboarding es que la lógica relacionada puede estar junto: estado, efectos secundarios y helpers en un lugar. El costo es la alfabetización en composables. Los nuevos contribuyentes necesitan entender patrones como useTableState() y cómo fluyen los valores reactivos a través de múltiples composables. Sin límites claros, puede sentirse como saltar entre archivos sin mapa.
Unas pocas convenciones eliminan la mayoría de las dudas, sea el estilo que elijas:
- Usa una estructura predecible:
components/,composables/,types/,tests/. - Escoge un patrón de nombres y síguelo (por ejemplo:
useX,XTable,XForm). - Añade docblocks cortos: qué hace el componente, props clave y eventos principales.
- Define una regla de “escape hatch” (cuándo está bien añadir un nuevo composable o helper).
- Mantén un pequeño componente “golden” que demuestre el patrón preferido.
Ejemplo: si tu equipo genera un panel admin en Vue 3 y luego lo personaliza (por ejemplo, una app web construida en AppMaster y extendida por desarrolladores), el onboarding mejora mucho cuando hay un lugar obvio para ajustar el comportamiento de tablas (ordenación, filtros, paginación) y un lugar obvio para ajustar el cableado UI (slots, renderizadores de columna, acciones de fila). Esa claridad importa más que la API que elijas.
Paso a paso: elegir un estilo e introducirlo sin riesgos
Para una gran biblioteca UI administrativa, la forma más segura de decidir es empezar con una característica bien acotada y tratarla como piloto, no como una reescritura.
Elige un módulo con comportamiento claro y alto potencial de reutilización, como filtrado de tablas o validación de formularios. Antes de tocar código, escribe qué hace hoy: entradas (props, params de query, acciones de usuario), salidas (eventos, emits, cambios en la URL) y casos límite (estado vacío, reset, errores del servidor).
Luego fija límites. Decide qué debe quedarse dentro del componente (renderizado, eventos DOM, detalles de accesibilidad) y qué puede moverse a código compartido (parseo de filtros, debounce, construir parámetros para la API, estado por defecto). Aquí es donde las bibliotecas suelen fallar: si mueves decisiones UI a código compartido, lo haces más difícil de reutilizar.
Un plan de despliegue práctico:
- Elige un componente que muestre el patrón claramente y lo usen varias pantallas.
- Extrae una unidad compartida (un composable o un helper plano) con una API pequeña y explícita.
- Añade una prueba enfocada para esa unidad primero, basada en escenarios reales de admin.
- Refactoriza el componente elegido de extremo a extremo usando la nueva unidad.
- Aplica el mismo patrón a otro componente para confirmar que escala.
Mantén la API compartida aburrida y obvia. Por ejemplo, un composable useTableFilters() podría aceptar filtros iniciales y exponer filters, apply(), reset() y una función toRequestParams(). Evita la “magia” que lee estado global a menos que eso ya sea una regla firme en tu app.
Después del piloto, publica una guía interna corta con un ejemplo que los contribuyentes puedan copiar. Una regla concreta vence a un documento largo, por ejemplo: “Toda la lógica de filtrado de tablas vive en un composable; los componentes solo enlazan controles UI y llaman a apply()”.
Antes de expandir el enfoque, usa una definición simple de hecho:
- El código nuevo se lee igual en dos componentes distintos.
- Las pruebas cubren la lógica compartida sin montar la UI completa.
- Un nuevo contribuyente puede cambiar una regla de filtro sin tocar archivos no relacionados.
Si tu equipo también construye portales admin con una herramienta no-code como AppMaster, puedes aplicar la misma mentalidad piloto allí: elige un flujo (por ejemplo aprobaciones), define comportamientos y estandariza el patrón antes de escalarlo a todo el producto.
Errores comunes y trampas en bibliotecas grandes
Los mayores problemas en una gran biblioteca rara vez son sintácticos. Provienen de pequeñas decisiones locales que se acumulan y hacen la reutilización, las pruebas y el mantenimiento más difíciles.
Una trampa común es mezclar patrones al azar. Si la mitad de la biblioteca usa Options API y la otra mitad usa Composition API sin regla, cada nuevo componente se convierte en un debate de estilo. También terminas con soluciones duplicadas a los mismos problemas (formularios, tablas, permisos) escritas en formas distintas. Si permites ambos, escribe una política clara: componentes nuevos usan un estilo, el legacy solo se toca cuando es necesario y la lógica compartida vive en un lugar acordado.
Otra trampa es el “god composable”. Suele empezar como un útil useAdminPage() o useTable() y lentamente absorbe routing, fetching, caché, selección, diálogos, toasts y permisos. Se vuelve difícil de probar porque una llamada dispara muchos efectos secundarios. También se vuelve difícil de reutilizar porque cada pantalla solo necesita el 30% pero paga la complejidad del 100%.
Los watchers son otra fuente de dolor. Son fáciles de añadir cuando algo parece desincronizado, pero los bugs de temporización aparecen después (especialmente con datos async y entradas con debounce). Cuando la gente reporta “a veces se me borra la selección”, puedes gastar horas reproduciéndolo.
Señales de alerta:
- Un componente funciona solo si se usa en un orden exacto de props y eventos.
- Un composable lee y escribe estado global sin dejarlo claro.
- Múltiples watchers actualizan el mismo trozo de estado.
- Los refactors siguen rompiendo pantallas consumidoras en pequeñas formas.
- Los contribuyentes evitan tocar “ese archivo” porque es arriesgado.
La última trampa es romper la API pública durante refactors. En apps administrativas, componentes como tablas, filtros y campos de formulario se propagan rápido. Renombrar una prop, cambiar un evento emitido o ajustar el comportamiento de un slot puede romper docenas de pantallas silenciosamente.
Un enfoque más seguro es tratar las APIs de los componentes como contratos: depreca en lugar de borrar, mantiene shims de compatibilidad un tiempo y añade pruebas simples de uso que monten el componente tal como lo hacen los consumidores. Si construyes interfaces admin generadas por herramientas como AppMaster, esto importa aún más: contratos consistentes facilitan reutilizar pantallas y mantener cambios previsibles.
Comprobaciones rápidas antes de comprometerte con un patrón
Antes de elegir Composition API, Options API o una mezcla, haz unas pruebas rápidas sobre componentes reales de tu biblioteca. El objetivo es simple: facilitar encontrar la lógica, reutilizar de forma segura y probar las partes de las que dependen realmente los admins.
1) ¿Alguien puede encontrar la lógica rápido?
Abre un componente típico con carga administrativa (filtros + tabla + permisos + acciones masivas). Finge que eres nuevo en el repo.
Una buena señal es cuando un contribuyente puede responder “¿dónde está la lógica de filtros?” o “¿qué decide si el botón está deshabilitado?” en menos de 2 minutos. Con Options API, esto suele significar que la lógica está claramente dividida en computed, methods y watchers. Con Composition API, significa que setup() está organizado en pequeños bloques nombrados (o composables) y evita una única función gigante.
2) ¿Las utilidades compartidas se comportan como funciones, no como magia?
Sea cual sea el patrón, el código compartido debe tener entradas y salidas claras y mínimos efectos secundarios. Si un helper toca estado global, muta objetos pasados o dispara llamadas de red sin que sea obvio, la reutilización se vuelve arriesgada.
Chequeo rápido:
- ¿Puedes leer la firma de un composable o helper y adivinar qué retorna?
- ¿Puedes usarlo en dos componentes sin configuración oculta?
- ¿Puedes resetear su estado en tests sin trucos?
3) ¿Tus pruebas se enfocan en comportamientos administrativos?
Las apps admin fallan de formas previsibles: filtros que aplican mal, permisos que dejan acciones visibles, formularios que validan incoherente y estado de tabla que se rompe tras ediciones.
En vez de probar detalles de implementación (watchers vs refs), escribe tests en torno al comportamiento: “dado rol X, la acción Y está oculta”, “al guardar muestra error y conserva la entrada del usuario”, “el cambio de filtro actualiza la query y el mensaje de estado vacío”. Esto mantiene las pruebas estables aunque refactores entre estilos.
4) ¿Tienen un estándar para estado async?
Las bibliotecas grandes acumulan muchos flujos async: cargar opciones, validar campos, obtener filas de tabla, reintentos. Si cada componente inventa su propio manejo de loading/error, el onboarding y el debug se vuelven lentos.
Elige una forma clara para estado async (loading, error, reintentos, cancelación). Composition API suele fomentar un composable useAsyncX(), mientras que Options API puede estandarizar un estado en data() más métodos compartidos. Cualquiera sirve si es consistente.
5) ¿Las APIs públicas de los componentes son estables y autoexplicativas?
Trata los componentes como productos. Sus props, eventos emitidos y slots son el contrato. Si ese contrato cambia a menudo, cada pantalla admin se vuelve frágil.
Busca comentarios que expliquen la intención (no la mecánica): qué significan las props, qué eventos se garantizan y qué se considera interno. Si construyes herramientas internas con una plataforma como AppMaster, esta misma mentalidad ayuda: bloques estables aceleran el envío de pantallas futuras.
Escenario de ejemplo y siguientes pasos para tu equipo
Imagina una página de “Usuarios” que vas a reconstruir: una barra de filtros (estado, rol, fecha de creación), una tabla con filas seleccionables, acciones masivas (deshabilitar, eliminar, exportar) y control por roles (solo admins pueden eliminar en bloque, managers pueden editar roles).
Con Composition API o Options API la UI puede verse igual, pero el código suele organizarse distinto.
En Options API, sueles acabar con un componente grande que tiene data para filtros y selección, computed para estado derivado y methods para fetch, acciones masivas y comprobaciones de permisos. La reutilización suele aparecer como mixins o módulos helper. Es familiar, pero la lógica relacionada puede dispersarse (fetch en methods, sync de query en watchers, permisos en computed).
En Composition API, típicamente separas la página en composables enfocados: uno para query y filtros, otro para selección de tabla y acciones masivas, y otro para permisos. El componente de página ensambla esas piezas y la lógica de cada preocupación se mantiene junta. El tradeoff es que necesitas nombres y convenciones de carpeta claras para que los contribuyentes no sientan que todo es “magia en setup”.
La reutilización suele surgir naturalmente en bibliotecas admin alrededor de filtros que sincronizan con la URL, patrones de tabla server-side (paginación, ordenación, select-all, guards para acciones masivas), comprobaciones de permisos y estados vacíos/cargando consistentes entre páginas.
Un plan de siguientes pasos que funciona para la mayoría de equipos:
- Elige un estilo por defecto para código nuevo y permite excepciones solo con una razón escrita.
- Define convenciones: dónde viven los composables, cómo se nombran, qué pueden importar y qué deben retornar.
- Añade una pequeña página de referencia (como esta página de Users) como estándar para patrones y estructura.
- Escribe pruebas primero para las partes reutilizables (filtros, permisos, acciones masivas), no para el layout visual.
- Si la velocidad importa más que la personalización profunda para algunas pantallas, considera generarlas con una herramienta no-code como AppMaster y reserva la biblioteca escrita a mano para las partes realmente únicas.
Si ya trabajas con AppMaster, ayuda mantener el mismo modelo mental entre las partes generadas y las hechas a mano: contratos de componente estables y lógica compartida empaquetada en unidades pequeñas y explícitas. Para equipos que evalúan no-code para herramientas internas, AppMaster está diseñado para generar aplicaciones completas (backend, web y móvil) y permitir estandarizar una UI web en Vue 3 cuando importa.
Si haces una sola cosa esta semana, toma la página de Usuarios como plantilla y hazla cumplir en las revisiones de código. Un ejemplo claro hará más por la consistencia que una guía larga.
FAQ
Por defecto usa la Composition API si tu biblioteca repite comportamientos como filtrado, paginación, acciones masivas y control por permisos. Facilita extraer lógica compartida en composables y mantiene las dependencias más explícitas. Usa la Options API cuando los componentes son mayormente presentacionales y la lógica es ligera.
La Options API agrupa el código por tipo (data, methods, computed, watch), por lo que la lógica de una funcionalidad suele quedar dispersa. La Composition API tiende a agrupar el código por característica, de modo que todo lo relativo a “filtros” o “selección” puede estar junto. El mejor criterio es el que haga que el próximo cambio sea fácil de encontrar y seguro de aplicar.
Con Options API, la reutilización suele empezar con mixins o extends, que pueden ocultar el origen de métodos y valores computados y provocar colisiones de nombres. Con Composition API, la reutilización se hace habitualmente con composables con entradas y salidas claras, por lo que el cableado es visible en el componente. En una biblioteca compartida, la reutilización explícita suele mantenerse más manejable por más tiempo.
Trátalo como una pequeña API: una tarea, parámetros claros y retornos previsibles. Si un composable empieza a mezclar paginación, caché, permisos y notificaciones, sepáralo en piezas más pequeñas. Composables pequeños son más fáciles de probar, reutilizar y menos propensos a producir efectos secundarios inesperados.
Mantén el contrato público estable: props, eventos emitidos y slots deben cambiar raramente. Coloca el formateo de entrada y la validación básica cerca de los componentes de campo, pero deja las reglas de negocio en composables o contenedores parentales. Así puedes refactorizar internamente sin forzar cambios en todas las pantallas.
La Composition API suele facilitar probar la lógica sin montar todo el componente, porque puedes testear composables y funciones puras directamente. Options API a menudo lleva a pruebas montadas en componentes donde watchers y el orden de ciclo de vida añaden ruido. Independientemente del estilo, separar reglas de negocio del cableado de UI mantiene las pruebas pequeñas y estables.
Estandariza una única forma de estado asíncrono como loading, error y una estrategia clara de reintento o cancelación. No permitas que cada componente invente sus propias convenciones; la depuración se vuelve lenta e inconsistente. Puedes implementar el estándar con cualquiera de las dos APIs, pero debe verse igual en toda la biblioteca.
Options API puede ser más fácil el primer día porque la estructura es familiar, pero los colaboradores pueden dedicar tiempo a unir la lógica dispersa entre bloques y mixins. Composition API suele ser más rápida una vez que la gente conoce tus composables y convenciones de carpetas, porque el comportamiento relacionado está agrupado y la reutilización es visible. La incorporación mejora mucho si proporcionas un componente “dorado” como ejemplo y aplicas los mismos patrones en las revisiones.
Elige un feature bien limitado y de alto uso (como filtrado de tablas o mapeo de errores de formulario) y trátalo como piloto. Extrae una unidad compartida con una API pequeña y explícita, escribe una prueba enfocada para ella y refactoriza un componente de extremo a extremo. Solo después de que el patrón funcione en al menos dos componentes amplíalo.
Observa duplicados cercanos, cadenas de watchers que se contraponen y componentes que solo funcionan con un orden exacto de props y eventos. Otro síntoma es cambiar props, eventos emitidos o slots con frecuencia. Si la gente evita tocar ciertos archivos porque son riesgosos, suele ser señal de que la biblioteca necesita contratos más claros y reutilización más explícita.


