Planteamiento y escenarios aplicables
El feed de actividad de un producto puede crecer hasta 100.000 elementos lógicos. Su API basada en cursores devuelve 50 elementos por solicitud. Una tarjeta puede medir entre 48 y 240 píxeles de alto después de que el texto se ajusta, una imagen se carga o los detalles se expanden. Los usuarios pueden filtrar el feed, expandir tarjetas y redactar respuestas en línea. Los usuarios de teclado y lectores de pantalla deben poder desplazarse por el feed sin perder el foco ni la información de posición.
Diseñe el rango de renderizado, la medición de alturas variables, la carga incremental, la propiedad del estado, el anclaje de desplazamiento, el comportamiento del foco, la semántica de accesibilidad y el plan de validación. Explique cuándo una lista paginada más simple o no virtualizada es la mejor opción.
La cantidad de elementos, el tamaño de página y el rango de altura son supuestos de entrevista, no objetivos universales de producto. Esta pregunta se adapta a roles de frontend senior, infraestructura de UI y rendimiento web. Su habilidad fundamental es el renderizado del navegador y el diseño de interacción, por lo que la categoría es frontend.
Qué evalúa el entrevistador
Primero, ¿puede el candidato separar cuatro responsabilidades que a menudo se confunden? La paginación controla qué registros ha cargado el cliente. La virtualización controla qué registros cargados tienen nodos en el DOM. La identidad estable controla qué registro de negocio es dueño del estado. La accesibilidad controla cómo un DOM parcial representa la colección lógica. Un mecanismo no resuelve los otros tres.
Segundo, ¿puede el candidato deducir la matemática de rangos a partir de los supuestos de tamaño de fila? Las filas de igual altura permiten aritmética directa de desplazamientos. Las filas de altura variable necesitan estimaciones, tamaños medidos, desplazamientos acumulados y una política de corrección cuando una estimación cambia. Una respuesta sólida nombra el salto de desplazamiento causado por el cambio de contenido por encima del viewport y preserva un anclaje lógico.
Tercero, ¿puede el candidato evitar la corrupción de estado? Un espacio visual reciclado no es un registro de negocio. Los borradores, la selección, la expansión y las mutaciones pendientes necesitan IDs de registro estables y un estado que sobreviva al desmontaje de una fila. El ordenamiento, el filtrado y las respuestas de páginas obsoletas no deben asociar datos o estado al índice incorrecto.
Cuarto, ¿puede el candidato mantener la accesibilidad intacta? Montar solo las tarjetas visibles elimina la mayor parte del conjunto lógico del DOM. Una respuesta sólida preserva la semántica nativa o de feed, expone la posición lógica y el tamaño del conjunto, anuncia el estado ocupado (busy) correctamente, mantiene montada la tarjeta con foco y proporciona una vía de carga operable.
Quinto, ¿puede el candidato validar el comportamiento en lugar de prometer un "desplazamiento fluido"? La respuesta debe definir dispositivos y escenarios objetivo, y luego medir la cantidad de nodos montados, el comportamiento de cuadros (frames) y tareas largas (long tasks), los cambios de diseño (layout shifts) o errores de anclaje, la duplicación de solicitudes, la memoria, la retención del foco y la salida para lectores de pantalla.
Preguntas para aclarar primero
- ¿La lista es verdaderamente lenta sin virtualización? Si el producto muestra a lo sumo unas pocas docenas de filas simples, el renderizado normal o la paginación es más fácil de mantener y más accesible. Mida antes de añadir windowing.
- ¿Las alturas de las filas son fijas, acotadas o arbitrarias? Las alturas fijas permiten matemáticas de rango en tiempo constante. Las alturas variables requieren estimaciones y medición. Los incrustados sin límites o medios tardíos dificultan la corrección del desplazamiento y pueden justificar diseños de tarjetas con restricciones.
- ¿La API expone un total de elementos o solo un cursor siguiente? Un total conocido puede respaldar un tamaño de conjunto lógico completo. Un total desconocido cambia las expectativas de la barra de desplazamiento y los metadatos de accesibilidad. La paginación por cursor también significa que los índices no cargados no son directamente direccionables.
- ¿Los usuarios deben poder saltar a un elemento arbitrario? Saltar por índice con filas variables y en su mayoría no medidas es aproximado hasta que se miden las filas cercanas. Saltar por ID de registro puede requerir una búsqueda en el servidor o una API diferente.
- ¿Qué estado de fila debe sobrevivir al desmontaje? El estado temporal de hover puede desaparecer. Los borradores de respuestas, la selección, la expansión, los errores de validación y las mutaciones optimistas suelen pertenecer al estado indexado por ID de registro fuera del componente de fila.
- ¿Qué modelo de teclado y semántica aplican? Un feed de lectura, un listbox seleccionable y una cuadrícula editable tienen diferentes roles y contratos de teclado. Elija el patrón semántico a partir de la interacción, no del diseño visual.
- ¿Cuál es el contrato de desplazamiento cuando los datos cambian? Tras filtrar, el producto puede reiniciarse arriba de todo. Cuando se anteponen elementos más antiguos, generalmente preserva el primer elemento visible actual. Cuando se anexan elementos en vivo, solo sigue el desplazamiento si el usuario ya estaba al final.
- ¿Cuáles son los objetivos de aceptación de rendimiento? Mencione dispositivos objetivo, forma de los datos, acciones de desplazamiento y presupuestos. Una traza de escritorio sobre filas mínimas con marcadores de posición no valida un feed móvil con imágenes y controles.
Estructura de respuesta de 30 segundos
"Mantendría la carga de datos, la virtualización y el estado de las filas separados. El cargador por cursor obtiene y deduplica páginas de 50 elementos. El virtualizador renderiza únicamente el rango visible más un pequeño overscan y posiciona esas filas dentro de un espaciador cuya altura representa los datos cargados. Las filas fijas usan aritmética de desplazamientos; las variables comienzan con estimaciones, se miden tras el layout y actualizan desplazamientos acumulados. Cuando una altura previa al viewport cambia, preservo el primer registro visible y su desplazamiento intra-fila para que la pantalla no salte. Cada fila utiliza el ID de registro, mientras que los borradores y la selección residen fuera de la fila. Para un feed de actividad, expondría la semántica de feed y article, la posición lógica y el tamaño del conjunto, el estado busy, y nunca desmontaría la tarjeta que contiene el foco. Probaría desplazamiento rápido, cambios de imagen y expansión, carreras de filtros, comportamiento al anteponer y anexar, navegación por teclado y lector de pantalla, conteo de nodos, tareas largas, memoria y error de anclaje. Si el renderizado ordinario ya cumple con el presupuesto, conservaría la lista más simple."
Análisis detallado paso a paso
Paso 1: Separar registros cargados de filas montadas
Mantenga un estado explícito para la capa de datos: IDs de registro ordenados, un mapa de ID a registro, el siguiente cursor, el estado de la solicitud y si existen más datos. El virtualizador recibe los IDs cargados ordenados y un contenedor de desplazamiento. No es dueño de los cursores, reintentos, borradores o mutaciones del servidor.
Con una API de cursor, inicialmente solo 50 registros son direccionables. Virtualice el prefijo cargado y aumente su altura lógica a medida que llegan las páginas. No finja que el índice no cargado 73.421 está disponible localmente a menos que la API admita acceso indexado o devuelva marcadores de posición con posiciones estables. El rango visible puede disparar una obtención cuando su final se acerca a la cantidad cargada, pero el cargador sigue siendo responsable de consolidar solicitudes y detenerse al llegar al final.
Esta separación previene dos errores comunes: una carga infinita que deja montados miles de nodos DOM antiguos, y un virtualizador que dispara solicitudes duplicadas cada vez que se recalcula su pequeño rango.
Paso 2: Deducir el rango de altura fija antes de añadir alturas variables
Para filas de igual altura, deduzca el primer y último índice visible a partir de scrollTop, la altura del viewport y la altura de la fila. El overscan expande el rango pero se limita a la cantidad cargada. Un lienzo interno de altura completa crea la barra de desplazamiento; las filas montadas se posicionan en sus desplazamientos lógicos.
function getFixedRange({
scrollTop,
viewportHeight,
rowHeight,
loadedCount,
overscanRows,
}) {
const visibleStart = Math.floor(scrollTop / rowHeight);
const visibleEnd = Math.ceil(
(scrollTop + viewportHeight) / rowHeight,
);
return {
start: Math.max(0, visibleStart - overscanRows),
end: Math.min(loadedCount, visibleEnd + overscanRows),
totalHeight: loadedCount * rowHeight,
};
}Renderice el intervalo semiabierto desde start hasta end, excluyendo end. Una fila en el índice i comienza en i * rowHeight. Actualice el rango desde el contenedor de desplazamiento, agrupe en lotes el renderizado con el framework y evite leer el layout y escribir estilos repetidamente dentro de una misma devolución de llamada de desplazamiento.
Esta solución es preferible cuando el diseño puede imponer una altura de fila única o un número pequeño de variantes conocidas. Es predecible, económica y fácil de restaurar. No adopte mediciones dinámicas simplemente porque la biblioteca las ofrece.
Paso 3: Medir filas variables y mantener desplazamientos acumulados
Las filas variables reemplazan la multiplicación por un modelo de tamaños. Inicie cada fila no medida con una estimación razonable basada en el diseño real de la tarjeta. Conserve los tamaños medidos por ID de registro, no por un espacio de DOM reciclado. El desplazamiento inicial de un elemento es la suma de los tamaños precedentes, por lo que encontrar el primer elemento visible se convierte en una búsqueda sobre desplazamientos acumulados.
Un arreglo de prefijos simple es fácil de explicar pero puede requerir actualizar muchos desplazamientos posteriores cuando una sola altura cambia. Una biblioteca de virtualización o una estructura de suma de prefijos indexada puede reducir el trabajo de búsqueda y actualización. La decisión de entrevista importante es el invariante: cada fila renderizada tiene un desplazamiento inicial lógico derivado del mismo almacén de tamaños, y la altura total del lienzo equivale a la suma de los tamaños actuales medidos o estimados.
Use ResizeObserver o el hook de medición de la biblioteca después de que una fila hace su layout. Reserve espacio para imágenes a partir de dimensiones conocidas siempre que sea posible; de lo contrario, la carga de una imagen produce una nueva medición. Ignore tamaños sin cambios, agrupe correcciones en lotes y desconecte observadores de filas que se desmontan. Vuelva a medir cuando el ancho, las métricas de fuentes, la expansión o los cambios de contenido puedan alterar la altura.
Se permite que las estimaciones sean erróneas. El sistema falla cuando cambia desplazamientos sin una política sobre qué debe seguir viendo el usuario.
Paso 4: Preservar un anclaje de desplazamiento lógico
Antes de aplicar cambios de tamaño, capture el ID del primer registro visible y la distancia desde su borde superior hasta el borde superior del viewport. Tras actualizar las mediciones y los desplazamientos acumulados, encuentre el nuevo inicio de ese registro y configure el desplazamiento de scroll para que el mismo punto intra-fila permanezca en la misma ubicación visual.
Si una fila ubicada completamente por encima del ancla crece 30 píxeles, el desplazamiento de scroll normalmente necesita la misma corrección de 30 píxeles. Un cambio por debajo del ancla no la necesita. Si el usuario está arrastrando la barra de desplazamiento o el producto navegó deliberadamente a un nuevo elemento, posponga o descarte la corrección de acuerdo con ese contrato de interacción.
Los navegadores también implementan anclaje de desplazamiento para cambios de layout ordinarios. Un virtualizador frecuentemente utiliza un lienzo sintético y filas con posicionamiento absoluto, por lo que el comportamiento nativo podría no preservar el elemento lógico previsto. Pruebe la combinación. Deje que el navegador o el virtualizador se encargue de la compensación para un contenedor dado; si el anclaje manual es autoritativo, desactive el anclaje nativo allí para evitar una doble corrección.
Anteponer registros más antiguos utiliza la misma regla. Capture el anclaje actual, inserte y mida los nuevos registros y luego restaure el anclaje. Anexar registros en vivo sigue el final únicamente cuando el usuario ya estaba dentro del umbral de "en lo más reciente" del producto; de lo contrario, muestre una acción de "nueva actividad" en lugar de mover el viewport.
Paso 5: Ajustar el overscan según el trabajo por fila y el comportamiento de desplazamiento
El overscan oculta la latencia de renderizado montando elementos justo fuera del viewport. Demasiado poco puede exponer espacios en blanco durante un desplazamiento rápido; demasiado recrea el costo de DOM, layout, memoria y efectos que la virtualización debía evitar. Con alturas variables, el overscan basado en píxeles suele ser más estable que un conteo fijo de filas porque cinco filas compactas y cinco filas expandidas representan trabajo y distancia diferentes.
Comience de forma conservadora, registre trazas en dispositivos objetivo y ajuste según la evidencia. Considere la dirección del desplazamiento, la velocidad, el costo de renderizado de la fila, la decodificación de imágenes y la latencia de actualización del framework. El overscan no sustituye memorizar trabajo pesado de la fila, reservar dimensiones de medios, cancelar efectos obsoletos o reducir lecturas síncronas de layout.
Mantenga un invariante estricto en el conteo de nodos: las filas montadas equivalen al rango visible, el overscan y un número reducido de filas fijadas explícitamente, como el elemento con foco. Un perfil de memoria debería mostrar que los componentes de fila, observadores y escuchadores de eventos antiguos pueden ser recolectados por el garbage collector tras salir de ese conjunto.
Paso 6: Cargar páginas sin condiciones de carrera ni registros duplicados
Dispare la carga desde el final del rango lógico en lugar de depender de un centinela que podría ser reciclado. Permita a lo sumo una solicitud por cursor. Almacene el cursor asociado con cada solicitud, deduplique registros devueltos mediante ID estable y deténgase cuando el servidor indique que no hay un cursor siguiente.
Filtrar u ordenar crea una nueva generación de consulta. Cancele la solicitud anterior cuando sea posible y rechace cualquier respuesta tardía cuya generación ya no coincida. Restablezca los IDs ordenados, el cursor, las mediciones que dependan del layout o contenido, y la posición de desplazamiento según el contrato del producto. Reutilizar desplazamientos antiguos para un nuevo orden asocia las alturas correctas a las posiciones incorrectas.
Los marcadores de posición de carga necesitan un tratamiento lógico estable. Si un único marcador de posición representa la página siguiente, no equivale a 50 registros accesibles. Si la API proporciona un total indexado conocido y el producto elige marcadores por fila, asígneles posiciones estables y reemplácelos sin cambiar de identidad. Siempre exponga estados de reintento y de fin de lista; una obtención fallida no debe dejar un espacio final en blanco permanente que parezca el final.
Paso 7: Mantener la identidad de los registros y el estado importante fuera de filas recicladas
Utilice el ID estable de cada registro como clave del framework (key) y clave de elemento del virtualizador. El índice del arreglo es inseguro cuando se anteponen páginas, los filtros reordenan registros o se eliminan duplicados. Un espacio reciclado puede mostrar el registro A ahora y el registro B después; el estado atado al espacio puede filtrar un borrador, casilla de verificación o resultado optimista entre registros de distintos usuarios.
Almacene el estado de UI persistente como mapas indexados por ID de registro: texto de borradores, expansión, selección, estado de validación y mutaciones pendientes. Una fila lee su porción cuando se monta y escribe a través de un propietario que sobrevive al desmontaje. El estado local es aceptable para detalles de presentación desechables cuya pérdida sea intencionada.
No retenga cada valor transitorio para siempre. Elimine el estado cuando el producto descarte una consulta, delimite la retención de borradores y concilie el estado optimista con los resultados del servidor. El objetivo es la pertenencia por identidad de negocio, no una caché de cliente sin límites.
Paso 8: Diseñar la accesibilidad como parte del algoritmo de rangos
Elija la semántica a partir de la interacción. Para un feed de lectura, el contenedor puede usar semántica de feed y cada tarjeta semántica de article con un nombre accesible. Cada artículo montado expone su posición lógica basada en uno (1-based). Si se conoce el total, exponga el total lógico; si se desconoce, use la representación de tamaño desconocido del patrón. Marque el feed como ocupado (busy) durante actualizaciones de múltiples operaciones y limpie siempre ese estado cuando la actualización termine.
No desmonte el elemento que contiene el foco del DOM. Añada el registro enfocado al rango montado incluso cuando caiga fuera del overscan normal, o mueva el foco mediante una acción deliberada de navegación antes de desalojarlo. Cuando los comandos de teclado se muevan al siguiente artículo lógico, asegúrese de que esté cargado y montado, desplácelo a la vista y luego enfóquelo. Documente cualquier tecla personalizada y preserve una forma confiable de desplazarse antes y después del feed.
La virtualización también puede romper la búsqueda en la página, la selección de texto del navegador, la impresión y el comportamiento de exploración de lectores de pantalla porque el contenido fuera de pantalla está ausente del DOM. Decida si esas características son requisitos. La búsqueda puede requerir un control respaldado por el servidor, la impresión puede renderizar una vista paginada independiente y un control explícito de "Cargar más" puede ofrecer una alternativa operable a la carga automática.
Por último, pruebe con operación exclusiva por teclado y lectores de pantalla reales. Inspeccionar atributos confirma el marcado pero no puede probar que el foco, los anuncios, la carga y la navegación funcionen en conjunto.
Paso 9: Validar una matriz de fallos, no solo un desplazamiento fluido
Construya un conjunto de datos determinista que contenga texto corto y largo, imágenes demoradas con dimensiones, expansión, medios faltantes e IDs duplicados. Pruebe desplazamiento lento y rápido con rueda, inercia táctil, arrastre de barra de desplazamiento, cambio de tamaño, zoom, carga de fuentes, cambios de filtro durante una solicitud, anteposición, anexión, fallo de obtención, reintento y fin de datos.
Registre la cantidad de filas montadas y nodos DOM durante la ejecución. Use una traza de rendimiento para inspeccionar cuadros, tareas largas, scripting, layout, pintura (paint) y mediciones repetidas inesperadas. Rastree la memoria pico y retenida después de desplazarse por muchas páginas. Compare el anclaje lógico superior antes y después de cambios de altura, y verifique que no aparezcan cursores ni IDs duplicados.
En cuanto a la interacción, coloque el foco en una fila, desplácese con el puntero y teclado, expanda filas por encima de ella, cargue la página siguiente y cambie filtros. Verifique dónde cae el foco y si los borradores se mantienen vinculados a los IDs correctos. Con un lector de pantalla, verifique nombres de artículos, posición lógica y tamaño del conjunto, transiciones de busy, navegación previa y siguiente, reintento y estado final.
El objetivo de aceptación corresponde al producto y a los dispositivos objetivo. Reporte trazas medidas y violaciones de invariantes en lugar de afirmar que la virtualización garantiza una tasa de cuadros particular.
Ejemplo de respuesta de alta calidad
"Modelaría el feed en tres capas. La capa de datos posee los IDs ordenados, los registros, el siguiente cursor, las generaciones de solicitudes y la deduplicación. El virtualizador recibe únicamente los IDs cargados y gestiona el rango visible, las mediciones y el posicionamiento. Los borradores, la expansión, la selección y las mutaciones residen en mapas indexados por ID de registro para que desmontar una fila no los elimine ni los mueva.
Para filas fijas, el rango es aritmética directa de desplazamientos y la altura del lienzo es la cantidad cargada multiplicada por la altura de fila. Como estas tarjetas varían de 48 a 240 píxeles, comenzaría con estimaciones, mediría las tarjetas montadas y mantendría desplazamientos acumulados. El primer registro visible y su desplazamiento intra-fila forman el anclaje de desplazamiento. Cuando una medición por encima de ese registro cambia, actualizo el desplazamiento de scroll por el delta resultante. Elegiría un único responsable de compensación para el contenedor para que el anclaje nativo y el manual no ajusten ambos el scroll.
El rango incluye un pequeño overscan medido más cualquier tarjeta enfocada. Cuando su final se acerca a la cantidad cargada, el cargador solicita el siguiente cursor una sola vez. Un cambio de filtro inicia una nueva generación, cancela la solicitud anterior cuando sea posible, rechaza resultados tardíos y restablece el orden y las mediciones. Los IDs de registro sirven como claves de elementos; los índices nunca son dueños del estado.
En cuanto a accesibilidad, este flujo de actividad utiliza semántica de feed y article. Los artículos montados exponen su posición lógica y total conocido, el feed expone el estado busy mientras se insertan páginas y ese estado se limpia después. No desmonto el artículo que contiene el foco. La navegación por teclado carga y monta el siguiente artículo lógico antes de enfocarlo, y mantengo vías explícitas de reintento, fin y carga manual.
Primero confirmaría que el renderizado ordinario no cumple con el presupuesto objetivo. Luego probaría una mezcla determinista de alturas de fila, medios demorados, expansiones, desplazamiento rápido, redimensionamiento, carreras de filtros, anteposición y anexión, y fallos de red. Registraría el conteo de nodos montados, tareas largas, trabajo de layout y pintura, memoria retenida, error de anclaje, solicitudes e IDs duplicados, identidad de borradores, foco de teclado y salida de lectores de pantalla. Si una lista paginada normal cumple los mismos requisitos, la elegiría porque tiene menos modos de fallo en cuanto a corrección y accesibilidad."
Errores comunes
- Tratar la carga infinita como virtualización → las páginas antiguas siguen añadiendo nodos DOM y el rendimiento se degrada con la distancia recorrida → limite el rango montado independientemente de los datos cargados.
- Usar índices de arreglo como claves de elementos → anteponer, filtrar y deduplicar mueven borradores y selecciones a registros diferentes → asigne keys a filas y estado externo mediante un ID de registro estable.
- Asumir que una altura promedio es exacta → el error de desplazamiento se acumula y causa rangos en blanco o saltos → mida filas variables y actualice un modelo de tamaño acumulado único.
- Aplicar cambios de medición sin un anclaje → el contenido por encima del viewport mueve lo que el usuario está leyendo → preserve el primer registro visible y su desplazamiento intra-fila.
- Dejar que el anclaje nativo y el manual compensen ambos → el viewport puede moverse dos veces → pruebe el contenedor y asigne la compensación a un solo responsable.
- Aplicar overscan con un número fijo y grande de filas → las tarjetas expandidas recrean trabajo pesado de DOM y layout → ajuste la distancia en píxeles y el costo de renderizado en dispositivos objetivo.
- Disparar una obtención en cada actualización de rango → renderizados repetidos solicitan el mismo cursor y entrelazan resultados → consolide por cursor y rechace generaciones de consulta obsoletas.
- Mantener borradores dentro de los componentes de fila → el desmontaje los elimina o la reutilización del slot los filtra a otros datos → eleve el estado importante a un propietario indexado por ID.
- Desmontar la fila con foco → el contexto del teclado y de tecnologías de asistencia desaparece → fije el elemento enfocado o mueva el foco deliberadamente antes del desalojo.
- Reportar solo la posición del subconjunto montado → un lector de pantalla escucha un tamaño de colección y orden engañosos → exponga la posición lógica y el tamaño del conjunto lógico conocido o desconocido.
- Establecer el estado busy y nunca limpiarlo → la tecnología de asistencia podría no exponer actualizaciones completadas → limpie el estado busy en cada ruta de éxito y fallo.
- Optimizar solo la tasa de cuadros → el foco, los borradores, las condiciones de carrera, la memoria y la posición de desplazamiento aún pueden ser incorrectos → valide los invariantes de rendimiento e interacción en conjunto.
Preguntas de seguimiento y respuestas
Seguimiento 1: ¿Qué cambia si cada fila mide exactamente 56 píxeles de alto?
Elimine la medición dinámica y sus vías de corrección. Calcule el rango y los desplazamientos directamente a partir de 56 píxeles, deduzca la altura total cargada mediante multiplicación y restaure posiciones por índice más el desplazamiento intra-fila. Conserve los IDs estables, el manejo de carreras de carga, el foco y la accesibilidad; la altura fija simplifica la geometría pero no resuelve la identidad ni la interacción. Haga pruebas de rendimiento (benchmark) antes de añadir una estructura de suma de prefijos que la restricción ya no necesita.
Seguimiento 2: ¿Cómo dar soporte a un total desconocido a partir de una API exclusiva por cursor?
Virtualice el prefijo cargado y expanda el lienzo cuando llegue una página. No invente índices no cargados ni un tamaño falso de barra de desplazamiento final. Exponga el tamaño de conjunto desconocido del patrón de feed, anuncie los estados de carga y de finalización, y mantenga un control explícito de carga adicional o reintento. El salto arbitrario por índice no está disponible a menos que el servidor añada búsqueda indexada, un localizador de registros o un contrato de estimación estable.
Seguimiento 3: Se anteponen elementos más antiguos mientras el usuario lee en el medio. ¿Cómo detener el salto?
Capture el ID del primer registro visible y su desplazamiento relativo al viewport antes de la inserción. Inserte los IDs más antiguos, estímelos o mídalos, recalcule los desplazamientos acumulados y ajuste el desplazamiento de scroll para que el registro capturado vuelva al mismo punto visual. Deduplique IDs en el límite de la página. Si la medición continúa después de cargar medios, aplique los deltas posteriores por encima del anclaje usando la misma regla.
Seguimiento 4: La tarjeta con foco está a 5.000 elementos de distancia tras arrastrar la barra de desplazamiento. ¿La mantiene montada para siempre?
Defina el contrato de interacción. Mantener una tarjeta enfocada fijada tiene un costo de DOM acotado, pero un objetivo de foco oculto lejos del viewport puede confundir a los usuarios. Durante un salto intencional de la barra de desplazamiento, mueva el foco al contenedor del feed o al artículo visible recién navegado con un anuncio, y luego desfije la tarjeta antigua. Durante mediciones imprevistas o desplazamientos con puntero, no destruya silenciosamente el foco. Pruebe el comportamiento elegido con usuarios de teclado y lectores de pantalla.
Seguimiento 5: El equipo de producto pide búsqueda en la página del navegador e imprimir los 100.000 elementos. ¿Puede un DOM virtualizado satisfacer eso?
Ningún DOM parcial confiable puede exponer texto que no esté montado a la búsqueda del navegador ni imprimirlo como contenido de página ordinario. Trátelos como requisitos separados. Proporcione una búsqueda respaldada por el servidor que se desplace y monte el registro coincidente. Genere una exportación paginada o una vista de datos específica para impresión con límites explícitos en lugar de montar temporalmente 100.000 tarjetas interactivas y congelar la página.
Seguimiento 6: ¿Cómo probaría un virtualizador sin depender únicamente de capturas de pantalla?
Pruebe los invariantes puros de rango fijo y desplazamientos acumulados con entradas deterministas, luego ejecute escenarios de integración en un navegador real. Asegure que los IDs montados cubran el rango visible y el overscan, que el tamaño total coincida con el modelo de tamaño, que el anclaje lógico se mantenga dentro de la tolerancia acordada tras la medición, que cada cursor se solicite una sola vez y que los borradores sigan a los IDs tras reordenar. Añada comprobaciones de teclado y lector de pantalla porque las aserciones de geometría del DOM no pueden validar el foco y los anuncios.