30 kwi 2023

window resize i optymalizacja

Czasami się zdarza, że musimy użyć "resize" 😉
Nie będę się rozpisywał co to jest wystarczy zerknąć tutaj - resize
Poniżej przykład użycia, a także wywołania jakiejś randomowej funkcji.

// nasz funkcja
function jakasFunkcja() {
  if (window.innerWidth < 600) {
     // tutaj coś robimy
  }
  else {
     // tutaj coś robimy
  }
}

// wywołanie funkcji
window.addEventListener('resize', jakasFunkcja);

Tak jak przypuszczasz, takie rozwiązanie jest bardzo złe ze względu na wydajność.
Dodaj console.log(); do funkcji i zobacz co się dzieje. Otwórz devtools i zobacz co wyświetla console.log podczas zmiany szerokości okna przeglądarki.

function jakasFunkcja() {
  console.log(window.innerWidth);
}

Tak funkcja jest wywoływana po 1px !!!
Oczywiście jest do prosta funkcja, a co jeżeli byłaby ona bardzo skomplikowana w której byśmy wyświetlali, setkę rekordów, modyfikowali DOM itp.

Możemy poprawić wydajność przez dodanie setTimeout.

let resizeTimer;
window.addEventListener('resize', () => {
  clearTimeout(resizeTimer);
  resizeTimer = setTimeout(() => {
    jakasFunkcja();
    console.log("test");
  }, 250);
});

Otwórz ponownie devtools i zobacz co się dzieje przy zmianie szerokości okna. Tak dobrze widzisz, teraz funkcja jest wywoływana gdy zatrzymamy zmianę okna. Brak jest setki wywołań funkcji jakasFunkcja

Istnieje jeszcze jeden moim zdaniem lepszy sposób wywołania funkcji gdy szerokość okna jest powiedzmy 600px.

Możemy użyć matchMedia. Poniżej kod obrazujący to w jaki sposób wywołać funkcję gdy szerokość okna ma maksymalnie 600px.

const mediaQuery = '(max-width: 600px)';
const mediaQueryList = window.matchMedia(mediaQuery);

mediaQueryList.addEventListener('change', event => {
  if (event.matches) {
     // tutaj coś robimy np. wywołujemy naszą funkcję jakasFunkcja();
  } else {
     // tutaj coś robimy
  }
})

Jak widzisz, wywołanie funkcji występuje tylko jeden raz gdy szerokość okna <= 600px.

Można również użyć matchMedia bez nasłuchiwania.

const mediaQueryList = window.matchMedia('(max-width: 600px)');

if(mediaQueryList.matches) {
   // tutaj coś robimy
}
else {
   // tutaj coś robimy
}

Co ciekawe możemy użyć różnych zapytań o mediaQuery, poniżej kilka z nich:

  • window.matchMedia('(orientation: portrait)')
  • window.matchMedia('screen and (max-width: 700px)')
  • window.matchMedia('(min-width: 700px)')