Improve
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* SigPro v2.0
|
* SigPro
|
||||||
*/
|
*/
|
||||||
(() => {
|
(() => {
|
||||||
let activeEffect = null;
|
let activeEffect = null;
|
||||||
@@ -7,7 +7,6 @@
|
|||||||
let isFlushScheduled = false;
|
let isFlushScheduled = false;
|
||||||
let flushCount = 0;
|
let flushCount = 0;
|
||||||
|
|
||||||
// --- Motor de Batching con Protección (v1 + v2) ---
|
|
||||||
const flushQueue = () => {
|
const flushQueue = () => {
|
||||||
isFlushScheduled = false;
|
isFlushScheduled = false;
|
||||||
flushCount++;
|
flushCount++;
|
||||||
@@ -21,7 +20,6 @@
|
|||||||
effectQueue.clear();
|
effectQueue.clear();
|
||||||
effects.forEach(fn => fn());
|
effects.forEach(fn => fn());
|
||||||
|
|
||||||
// Resetear contador al final del microtask
|
|
||||||
queueMicrotask(() => flushCount = 0);
|
queueMicrotask(() => flushCount = 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -36,29 +34,26 @@
|
|||||||
const $ = (initial, key) => {
|
const $ = (initial, key) => {
|
||||||
const subs = new Set();
|
const subs = new Set();
|
||||||
|
|
||||||
// 1. Objetos Reactivos (v2)
|
|
||||||
if (initial?.constructor === Object && !key) {
|
if (initial?.constructor === Object && !key) {
|
||||||
const store = {};
|
const store = {};
|
||||||
for (let k in initial) store[k] = $(initial[k]);
|
for (let k in initial) store[k] = $(initial[k]);
|
||||||
return store;
|
return store;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. Efectos y Computados con Limpieza (v1 + v2)
|
|
||||||
if (typeof initial === 'function') {
|
if (typeof initial === 'function') {
|
||||||
let cached, running = false;
|
let cached, running = false;
|
||||||
const cleanups = new Set();
|
const cleanups = new Set();
|
||||||
|
|
||||||
const runner = () => {
|
const runner = () => {
|
||||||
if (runner.el && !runner.el.isConnected) return; // GC: v2
|
if (runner.el && !runner.el.isConnected) return;
|
||||||
if (running) return;
|
if (running) return;
|
||||||
|
|
||||||
// Ejecutar limpiezas previas (v1)
|
|
||||||
cleanups.forEach(fn => fn());
|
cleanups.forEach(fn => fn());
|
||||||
cleanups.clear();
|
cleanups.clear();
|
||||||
|
|
||||||
const prev = activeEffect;
|
const prev = activeEffect;
|
||||||
activeEffect = runner;
|
activeEffect = runner;
|
||||||
activeEffect.onCleanup = (fn) => cleanups.add(fn); // Registro de limpieza
|
activeEffect.onCleanup = (fn) => cleanups.add(fn);
|
||||||
|
|
||||||
running = true;
|
running = true;
|
||||||
try {
|
try {
|
||||||
@@ -79,13 +74,11 @@
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Persistencia (v2)
|
|
||||||
if (key) {
|
if (key) {
|
||||||
const saved = localStorage.getItem(key);
|
const saved = localStorage.getItem(key);
|
||||||
if (saved !== null) try { initial = JSON.parse(saved); } catch (e) { }
|
if (saved !== null) try { initial = JSON.parse(saved); } catch (e) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. Señal Atómica
|
|
||||||
return (...args) => {
|
return (...args) => {
|
||||||
if (args.length) {
|
if (args.length) {
|
||||||
const next = typeof args[0] === 'function' ? args[0](initial) : args[0];
|
const next = typeof args[0] === 'function' ? args[0](initial) : args[0];
|
||||||
@@ -103,7 +96,6 @@
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// --- Motor de Renderizado con Modificadores de v1 ---
|
|
||||||
$.html = (tag, props = {}, content = []) => {
|
$.html = (tag, props = {}, content = []) => {
|
||||||
const el = document.createElement(tag);
|
const el = document.createElement(tag);
|
||||||
if (props instanceof Node || Array.isArray(props) || typeof props !== 'object') {
|
if (props instanceof Node || Array.isArray(props) || typeof props !== 'object') {
|
||||||
@@ -179,12 +171,9 @@
|
|||||||
const tags = ['div', 'span', 'p', 'h1', 'h2', 'ul', 'li', 'button', 'input', 'label', 'form', 'section', 'a', 'img'];
|
const tags = ['div', 'span', 'p', 'h1', 'h2', 'ul', 'li', 'button', 'input', 'label', 'form', 'section', 'a', 'img'];
|
||||||
tags.forEach(t => window[t] = (p, c) => $.html(t, p, c));
|
tags.forEach(t => window[t] = (p, c) => $.html(t, p, c));
|
||||||
|
|
||||||
// --- Router mejorado ---
|
|
||||||
$.router = (routes) => {
|
$.router = (routes) => {
|
||||||
// Señal persistente del path actual
|
|
||||||
const sPath = $(window.location.hash.replace(/^#/, "") || "/");
|
const sPath = $(window.location.hash.replace(/^#/, "") || "/");
|
||||||
|
|
||||||
// Listener nativo
|
|
||||||
window.addEventListener("hashchange", () => sPath(window.location.hash.replace(/^#/, "") || "/"));
|
window.addEventListener("hashchange", () => sPath(window.location.hash.replace(/^#/, "") || "/"));
|
||||||
|
|
||||||
const container = div({ class: "router-outlet" });
|
const container = div({ class: "router-outlet" });
|
||||||
@@ -193,7 +182,6 @@
|
|||||||
const cur = sPath();
|
const cur = sPath();
|
||||||
const cP = cur.split('/').filter(Boolean);
|
const cP = cur.split('/').filter(Boolean);
|
||||||
|
|
||||||
// Buscamos la ruta (incluyendo parámetros :id y wildcard *)
|
|
||||||
const route = routes.find(r => {
|
const route = routes.find(r => {
|
||||||
const rP = r.path.split('/').filter(Boolean);
|
const rP = r.path.split('/').filter(Boolean);
|
||||||
return rP.length === cP.length && rP.every((p, i) => p.startsWith(':') || p === cP[i]);
|
return rP.length === cP.length && rP.every((p, i) => p.startsWith(':') || p === cP[i]);
|
||||||
@@ -201,7 +189,6 @@
|
|||||||
|
|
||||||
if (!route) return container.replaceChildren(h1("404 - Not Found"));
|
if (!route) return container.replaceChildren(h1("404 - Not Found"));
|
||||||
|
|
||||||
// Extraer parámetros dinámicos
|
|
||||||
const params = {};
|
const params = {};
|
||||||
route.path.split('/').filter(Boolean).forEach((p, i) => {
|
route.path.split('/').filter(Boolean).forEach((p, i) => {
|
||||||
if (p.startsWith(':')) params[p.slice(1)] = cP[i];
|
if (p.startsWith(':')) params[p.slice(1)] = cP[i];
|
||||||
@@ -209,7 +196,6 @@
|
|||||||
|
|
||||||
const res = typeof route.component === 'function' ? route.component(params) : route.component;
|
const res = typeof route.component === 'function' ? route.component(params) : route.component;
|
||||||
|
|
||||||
// Renderizado Seguro con replaceChildren (v1 spirit)
|
|
||||||
if (res instanceof Promise) {
|
if (res instanceof Promise) {
|
||||||
const loader = span("Cargando...");
|
const loader = span("Cargando...");
|
||||||
container.replaceChildren(loader);
|
container.replaceChildren(loader);
|
||||||
@@ -219,13 +205,12 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
routeEff.el = container; // Seguridad de SigPro v2
|
routeEff.el = container;
|
||||||
$(routeEff);
|
$(routeEff);
|
||||||
|
|
||||||
return container;
|
return container;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Vinculamos el método .go
|
|
||||||
$.router.go = (path) => {
|
$.router.go = (path) => {
|
||||||
const target = path.startsWith('/') ? path : `/${path}`;
|
const target = path.startsWith('/') ? path : `/${path}`;
|
||||||
window.location.hash = target;
|
window.location.hash = target;
|
||||||
@@ -237,4 +222,5 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
window.$ = $;
|
window.$ = $;
|
||||||
})();
|
})();
|
||||||
|
export const { $ } = window;
|
||||||
Reference in New Issue
Block a user