Posterior a consultar especialistas en la materia, programadores de deferentes áreas y maestros hemos dado con la respuesta al dilema y la compartimos en este post.
Solución:
Pon este código dentro de tu componente Vue:
created()
window.addEventListener("resize", this.myEventHandler);
,
destroyed()
window.removeEventListener("resize", this.myEventHandler);
,
methods:
myEventHandler(e)
// your code for handling resize...
Esto registrará su método Vue en la creación del componente, activará myEventHandler cuando se cambie el tamaño de la ventana del navegador y liberará memoria una vez que se destruya su componente.
Enfoque más simple
https://www.npmjs.com/package/vue-window-size
Avance
import Vue from 'vue';
import VueWindowSize from 'vue-window-size';
Vue.use(VueWindowSize);
Luego accedería normalmente desde sus componentes de esta manera:
window width: windowWidth
window height: windowHeight
Miré el código de esa biblioteca. vue-window-size
, y además de la lógica adicional, solo agrega un detector de eventos en el cambio de tamaño de la ventana, y parece que se le puede indicar que rebote. Fuente
El problema crítico para mí es que mi aplicación Vue SPA no emite un evento de cambio de tamaño de ventana cuando cambia una ruta de vue-router que hace que el elemento va de 1000px a 4000px, por lo que me está causando todo tipo de problemas al ver un elemento de lienzo controlado por p5.js para volver a dibujar un fondo de pantalla usando
p5.resizeCanvas()
.
Ahora tengo una solución diferente que implica sondear activamente la altura de compensación de la página.
Lo primero que debe tener en cuenta es la gestión de la memoria de JavaScript, por lo que para evitar pérdidas de memoria, puse setInterval en el created
método de ciclo de vida y clearInterval en el beforeDestroy
método del ciclo de vida:
created()
this.refreshScrollableArea = setInterval(() =>
const offsetWidth, offsetHeight = document.getElementById('app');
this.offsetWidth = offsetWidth;
this.offsetHeight = offsetHeight;
, 100);
,
beforeDestroy()
return clearInterval(this.refreshScrollableArea);
,
Como se insinuó en el código anterior, también coloqué un estado inicial:
data()
const offsetWidth, offsetHeight = document.querySelector('#app');
return
offsetWidth,
offsetHeight,
refreshScrollableArea: undefined,
;
,
Nota: si estás usando
getElementById
con algo comothis.id
(es decir: un elemento que es un hijo en este componente),document.getElementById(this.id)
estará indefinido porque los elementos DOM se cargan de afuera hacia adentro, por lo que si ve un error derivado deldata
creación de instancias, establezca el ancho/alto en0
inicialmente.
Luego, puse un vigilante offsetHeight
para escuchar los cambios de altura y realizar la lógica empresarial:
watch:
offsetHeight()
console.log('offsetHeight changed', this.offsetHeight);
this.state = IS_RESET;
this.setState(this.sketch);
return this.draw(this.sketch);
,
,
Conclusión: probé con performance.now()
y:
document.querySelector('#app').offsetHeight
document.getElementById('app').offsetHeight
document.querySelector('#app').getClientBoundingRect().height
todos se ejecutan en aproximadamente la misma cantidad de tiempo: 0.2ms
, por lo que el código anterior cuesta alrededor de 0,2 ms cada 100 ms. Actualmente encuentro eso razonable en mi aplicación, incluso después de ajustar los clientes lentos que operan un orden de magnitud más lento que mi máquina local.
Esta es la lógica de prueba para su propia I+D:
const t0 = performance.now();
const offsetWidth, offsetHeight = document.getElementById('app');
const t1 = performance.now();
console.log('execution time:', (t1 - t0), 'ms');
Prima: si tiene algún problema de rendimiento debido a un tiempo de ejecución prolongado en su setInterval
función, intente envolverlo en un marco de animación de doble solicitud:
created()
this.refreshScrollableArea = setInterval(() =>
return requestAnimationFrame(() => requestAnimationFrame(() =>
const offsetWidth, offsetHeight = document.getElementById(this.id);
this.offsetWidth = offsetWidth;
this.offsetHeight = offsetHeight;
));
, 100);
,
requestAnimationFrame
en sí mismo una persona debe investigar. Lo dejaré fuera del alcance de esta respuesta.
Para terminar, otra idea que investigué más tarde, pero que no estoy usando, es usar un método recursivo setTimeout
función con un tiempo de espera dinámico (es decir, un tiempo de espera que decae después de que se carga la página); sin embargo, si considera la técnica recursiva setTimeout, tenga en cuenta la longitud de la pila de llamadas/cola de funciones y la optimización de las llamadas finales. El tamaño de la pila podría escaparse de ti.
Acuérdate de que tienes concesión de reseñar tu experiencia si te ayudó.