__date__

Reactive

Descripción

Proporciona enlace de datos bidireccional y reactividad síncrona y optimizada con el DOM. Sincroniza de manera automática el estado del script con la interfaz de usuario utilizando plantillas de delimitadores configurables (por defecto, {{ variable }}).

Librería: estructura.reactive.js

Documentación

1. Inicialización y Estado

Inicialice la reactividad seleccionando un nodo del DOM (por lo general, el nodo raíz de la vista). Acceda al estado reactivo utilizando el objeto Proxy devuelto por el método .state().

// Inicializar reactividad sobre el documento
var miReactivo = _reactive(document.documentElement);

// Obtener el objeto de estado
var state = miReactivo.state();

// Escribir propiedades en el estado
state.miVariable = 'Hola Mundo';

2. Configuración Avanzada

El constructor acepta un segundo argumento opcional (Object) para configurar delimitadores personalizados de plantillas y procesadores dinámicos de nombres y expresiones.


Opciones de Configuración:

  • variables_prefix (String): Delimitador de apertura de la plantilla (por defecto, "{{").

  • variables_postfix (String): Delimitador de cierre de la plantilla (por defecto, "}}").

  • variables_preprocessor (Function): Callback que se ejecuta inmediatamente al extraer variables. Recibe el nombre crudo de la variable y un objeto de metadatos ({ expr, start, end }). Permite filtrar o reescribir variables en tiempo de compilación.

  • variables_processor (Function): Callback que inicializa valores de expresiones complejas o rutas anidadas en el objeto de estado de manera inicial (se ejecuta una única vez en el momento del registro). Recibe el identificador virtual generado (String), la expresión original del DOM (String) y el estado expuesto (Object).

Ejemplo de Configuración:

var miReactivo = _reactive(document.documentElement, {
	variables_prefix: '[[',
	variables_postfix: ']]',
	variables_preprocessor: function(name, meta) {
		// Ignorar variables específicas retornando un valor falso
		if (name === 'ignore_me') return null;
		return name.toLowerCase();
	},
	variables_processor: function(key, expr, state){
		try {
			var keys = Object.keys(state);
			var vals = keys.map(function(k){ return state[k]; });
			return new Function(keys, 'return (' + expr + ')').apply(null, vals);
		} catch(e){ return ''; }
	}
});

3. Enlace de Datos (Templates) y Expresiones

El compilador de la librería analiza el contenido sintáctico y clasifica las plantillas en dos categorías de manera automática:


  • Identificadores Simples: Si el texto cumple con la regla de un identificador válido de JavaScript (ej. nombre, mi_variable), se registra de forma directa y nativa en el estado reactivo.

  • Expresiones Complejas u Operaciones: Si el texto contiene operadores, espacios o rutas de objeto (ej. user.name o 1 * 2), el motor lo detecta como expresión, lo aísla del preprocesador (no aplica el preprocesador automáticamente sobre la expresión, pero la expone mediante el metadata { expr: true }) y genera una clave de estado virtual única basada en posiciones de carácter dentro del texto (ej. _e_7_18). Esto protege el objeto de estado y permite evaluar cálculos o rutas anidadas mediante el variables_processor.

Enlace Unidireccional

Se aplica en nodos de texto estándar y en atributos comunes (como class, src, id, etc.). Permite múltiples variables o expresiones en una sola línea.

<!-- Nodos de texto con identificadores y expresiones -->
<h1>Bienvenido, {{nombre}} {{apellido}}</h1>
<p>Operación: {{1 * 2}}</p>
<p>Ruta anidada: {{user.name}}</p>

<!-- Atributos -->
<div class="alerta {{tipo_alerta}}" id="{{id_registro}}"></div>

Enlace Bidireccional

Sincroniza en tiempo real los cambios de entrada de la interfaz con el estado reactivo. Soporta atributos de entrada (value, checked) y nodos de texto dentro de elementos <textarea>. Para evitar colisiones de escritura, estos elementos solo admiten un único enlace directo a un identificador simple.

<!-- Input de texto -->
<input type="text" value="{{miVariable}}">

<!-- Control booleano -->
<input type="checkbox" checked="{{activo}}">

<!-- Textarea -->
<textarea>{{miVariable}}</textarea>

4. Control del Ciclo de Vida

La instancia reactiva expone métodos protegidos en el estado para activar, pausar o apagar la ejecución del motor.


  • state.on(): Activa la reactividad, compila las plantillas del DOM por primera vez de forma síncrona e inicializa los observadores. Se ejecuta automáticamente en el arranque (puede llamarse manualmente después de un stop() para reanudar).

  • state.stop(): Pausa la reactividad deteniendo el flujo de eventos e interrumpiendo temporalmente el observador de mutaciones, sin perder los registros internos ni los datos del estado.

  • state.off(): Apaga y desmantela completamente la reactividad, deteniendo el motor, eliminando registros y liberando la memoria asignada.

5. Sistema de Eventos (Hooks)

Permite suscribir callbacks a eventos específicos del ciclo de vida de las variables y del motor reactivo mediante el método de registro state.event(). Los callbacks se ejecutan en un contexto aislado y protegido contra errores.


Sintaxis:

state.event('createdVariable', function(name) {
	console.log('Variable registrada:', name);
});

Eventos Soportados:

  • createdVariable: Se dispara cuando una variable se registra en el DOM por primera vez. Recibe como argumento el nombre de la variable (String).

  • deletedVariable: Se dispara cuando una variable pierde todas sus vinculaciones con nodos del DOM. Recibe el nombre de la variable (String).

  • beforeMutateVariable: Se dispara antes de actualizar el DOM. Recibe la variable (String), el valor nuevo, el elemento contenedor nativo del DOM (Element), el nodo físico exacto que muta y el nombre de la propiedad o atributo.

  • afterMutateVariable: Se dispara tras actualizar el DOM. Recibe los mismos argumentos que el evento before.

  • reactiveOn: Se ejecuta cuando se activa el motor de reactividad.

  • reactiveStop: Se ejecuta cuando se pausa el motor.

  • reactiveOff: Se ejecuta cuando se apaga y desmonta el motor.

6. Características Técnicas

Batching síncrono por microtareas: Agrupa múltiples actualizaciones consecutivas del estado en una sola tarea de microsegundo mediante promesas nativas, previniendo actualizaciones redundantes en el DOM.


Compilación síncrona en un paso: El procesador auxiliar compila y extrae de forma limpia las variables recorriendo de manera única los índices impares del arreglo compilado, evitando dobles bucles de escaneo.


MutationObserver dinámico con guardas: Monitorea en tiempo real adición, remoción o cambios estructurales del DOM, asociando reactividad a elementos nuevos y limpiando de forma segura los destruidos. La validación de conexión nativa (.isConnected) garantiza que los callbacks de eventos nunca operen sobre nodos huérfanos.


Gestión defensiva de memoria: Utiliza estructuras WeakMap para almacenar datos de plantillas y registros de elementos, garantizando que los nodos removidos puedan ser procesados por el recolector de basura sin fugas de memoria.