Fundamentos del motor de enrutamiento
El subsistema de rutas en uni-app opera sobre una estructura tipo pila (LIFO). Cada interacción de interfaz modifica esta colección de vistas según reglas estrictas. Seleccionar la API correcta garantiza un comportamiento predecible del historial de pantallas y evita fugas de memoria o transiciones rotas.
Referencia rápida de métodos nativos
| Método | Efecto en la pila | Preserva la vista origen | Soporte para TabBar | Pasaje de datos |
|---|---|---|---|---|
uni.navigateTo |
Añade un nivel (+1) | Sí | No permitido | Vía cadena de consulta |
uni.redirectTo |
Reemplaza el nivel actual (0 cambios netos) | No | No permitido | Vía cadena de consulta |
uni.reLaunch |
Vacía toda la colección (reseteo total) | No | Permitido | Vía cadena de consulta |
uni.switchTab |
Descarta rutas intermedias, activa la pestaña definida | No | Exclusivo | Requiere almacén global o bus de eventos |
uni.navigateBack |
Retira n niveles (-n) | - | - | No nativo (usar patrón publish/subscribe) |
Implementación y casos de uso
Desplazamiento preservando contexto
uni.navigateTo empuja una nueva ruta sobre la pila. Es el estándar para formularios secuenciales, módulos de detalle o cualquier flujo que exija retroceso inmediato. La pila tiene un límite operativo de diez elementos; superar este umbral genera descarte automático del registro más antiguo.
const iniciarProceso = async (targetId) => {
try {
await uni.navigateTo({
url: `/workflows/step-one?ref=${encodeURIComponent(targetId)}&stage=pending`
});
} catch (error) {
console.error('Fallo en la navegación:', error.errMsg);
}
};
// Captura en la vista destino
onLoad(queryParams) {
this.referenceId = queryParams.ref;
this.stageStatus = queryParams.stage;
}
Sustitución de ruta actual
uni.redirectTo elimina la página padre antes de renderizar la siguiente. Resulta idóneo cuando la experiencia no debe permitir volver atrás, como en flujos de checkout finalizados o autenticaciones exitosas. El contador de profundidad permanece inalterado.
const actualizarDestino = () => {
uni.redirectTo({
url: '/modules/success-report',
complete: () => console.log('Entorno sustituido correctamente')
});
};
Reseteo completo de vistas
uni.reLaunch destruye la pila existente y carga una ruta absoluta. Es crucial para cerrar sesiones, reconfigurar el entorno de desarrollo o garantizar que la aplicación arranque desde un estado limpio. Admite parámetros en la URI aunque borra todo el historial acumulado.
const reiniciarSesion = () => {
uni.reLaunch({
url: '/auth/welcome-screen'
});
};
Activación de pestañas inferiores
La única vía oficial para interactuar con rutas marcadas como TabBar es uni.switchTab. Internamente, cierra automáticamente todas las capas no pertenecientes a la barra principal y fuerza la reconstrucción de la pestaña seleccionada. Su diseño excluye la transmisión directa mediante url; los valores de consulta son ignorados por el compilador.
const activarPestañaCentral = () => {
uni.switchTab({ url: '/tabs/main-dashboard' });
};
Retroceso controlado
uni.navigateBack opera sobre la pila mediante un desplazador numérico. Si el valor supera los registros disponibles, la aplicación salta silenciosamente a la ruta raíz. Importante: la ejecución de este método dispara el gancho onShow en la página recuperada, facilitando oepraciones de actualización sin necesidad de recargas manuales.
const avanzarRetroceso = (escalones = 1) => {
uni.navigateBack({ delta: escalones });
};
// Sincronización automática en vista restaurada
onShow() {
this.obtenerRegistrosActualizados();
}
Gestión avanzada de estado cruzado
Utilidad de enrutamiento inteligente
Aislamos la lógica de detección de rutas y codificación de parámetros en un gestor centralizado. Este enfoque automatiza la selección de API según la naturaleza de la dirección destino.
class PathManager {
constructor(tabBarRoutes) {
this.exclusiveRoutes = tabBarRoutes;
}
navegarA(ruta, opciones = {}) {
const esPestaña = this.exclusiveRoutes.includes(ruta);
const cadenaConsulta = this.formatearQuery(opciones);
const target = `${ruta}${cadenaConsulta}`;
if (esPestaña) {
this.transmitirDatos(opciones);
uni.switchTab({ url: ruta });
} else {
uni.navigateTo({ url: target });
}
}
formatearQuery(pares) {
const entries = Object.entries(pares);
if (!entries.length) return '';
const segments = entries.map(([k, v]) => `${k}=${encodeURIComponent(v)}`);
return `?${segments.join('&')}`;
}
transmitirDatos(payload) {
uni.$emit('datosPestaña', payload);
}
}
export default new PathManager(['/tabs/home', '/tabs/profile']);
Sincronización persistente para TabBar
Dado que switchTab desecha la pila intermedia, el almacenamiento local de instancia o variables globales resultan insuficientes si la aplicación sufre GC agresivo. Un módulo Vuex dedicado mantiene contratos seguros entre pantallas independientes.
// store/modules/route-sync.js
export default {
namespaced: true,
state: () => ({
contextoSesión: null,
flagRecargaContenido: false
}),
mutations: {
vincularContexto(state, info) {
state.contextoSesión = info;
},
solicitarRefresco(state, activo) {
state.flagRecargaContenido = activo;
}
},
actions: {
sincronizarYmover({ commit }, ruta, cargaÚtil) {
if (cargaÚtil) {
commit('vincularContexto', cargaÚtil);
commit('solicitarRefresco', true);
}
uni.switchTab({ url: ruta });
}
}
};
// Consumo en origen
this.$store.dispatch('route-sync/sincronizarYmover', '/tabs/reports', { filtroMes: '11' });
Observabilidad y diagnóstico de rutas
Monitorear la pila activa previene errores como colapsos por saturación de memoria o redirecciones bloqueadas. El objeto getCurrentPages() expone metadatos de cada nodo registrado.
const inspeccionarPila = () => {
const nodos = getCurrentPages();
console.group('Topología de vistas');
console.log(`Profundidad total: ${nodos.length}`);
console.log(`Vista superior: ${nodos[nodos.length - 1]?.route ?? 'vacía'}`);
console.log(`Predecesora: ${nodos[nodos.length - 2]?.route ?? 'inválida'}`);
console.groupEnd();
};
// Instrumentación a nivel de aplicación
Page({
onHide() { console.warn('Aplicación suspendida o cambiada de foco'); },
onShow() { inspeccionarPila(); }
});
Prevención de activaciones redundantes
Los gestos táctiles accidentales pueden disparar múltiples solicitudes simultáneas. Un mecanismo de anti-rebote a nivel modular garantiza intervalos mínimos entre transiciones críticas.
let temporizadorBloqueo = null;
const ACCESO_SEGURIDAD = 600; // milisegundos
const navegarConCautela = (destino) => {
const ahora = Date.now();
if (temporizadorBloqueo && (ahora - temporizadorBloqueo) < ACCESO_SEGURIDAD) {
console.debug('Transacción ignorada por ventana de seguridad');
return;
}
temporizadorBloqueo = ahora;
uni.navigateTo({ url: destino });
};
Mapeo de errores frecuentes
fail can not switch to a tabBar page: Ocurre al usarnavigateTooredirectTosobre rutas declaradas como pestañas. La corrección implica derivar automáticamente aswitchTab.fail page limit exceeded: Indica saturación de los diez niveles permitidos. Mitigaciones: emplearredirectTopara substituir, invocarreLaunchpara purgar, o retroceder explícitamente antes de avanzar.- Pérdida de parámetros en pestañas: Las URIs enviadas a
switchTabse truncan. Migrar obligatoriamente a inyección vía$emit, estados Vuex o variables persistentes engetApp().globalData.