javascriptvuejs3resize-observer

JavaScript ResizeObserver keeps on calling itself after unobserving the element


In a component of a Vue3 app I am building I want to observe an HTML Element and when it resizes I want to trigger some computations that resize the Element a couple of times. Once the final value is known I want to turn the observing back on.

I am using ResizeObserver for this and copied this solution from this anwser.

<script setup>
  import { ref, onMounted } from 'vue'

  const a = ref(null)
  let resizeObserver = null

  onMounted (() => {
    const element = document.getElementById('a-span')
    a.value.textContent = 'resize'

    resizeObserver = new ResizeObserver((entries) => {

      resizeObserver.disconnect(element)

      a.value.textContent = a.value.textContent.concat('- some text- ')

      setTimeout(() => {
        resizeObserver.observe(element)
        }, 1000)
    })

    resizeObserver.observe(element)
  })
</script>

<template>
  <span id="a-span" ref="a">no text</span>
</template>

No matter how many Milliseconds I make it wait, it will call itself over-and-over again.

I have the feeling that .observe(element) does an initial call to the (entries) => { so I tried putting an if (runCode) { around the ResizeObserver logic and set runCode = false at the beginning and back to true at the end. This also doesn't work...

What is the best way to observe an HTML element for size and when it changes preform a 1001 changes to that element. Then after it is done again check if the size of the element changes?


Solution

  • @diachedelic pointed out: "ResizeObserver ignores element if it has inline display. Try using a <div> instead."

    The anwser by @Ale_blianco has two errors in it and I can't edit it. So here is the correct code:

    <template>
      <div id="a-div" ref="a">no text</div> <!-- this was a span should be a div -->
    </template>
    
    <script setup>
    import { ref, onMounted } from 'vue';
    
    const a = ref(null);
    let resizeObserver = null;
    let width;
    
    onMounted(() => {
      const element = document.getElementById('a-div');
      a.value.textContent = 'resize';
    
      resizeObserver = new ResizeObserver(function on_resize(entries) {
        if (entries[0].contentRect.width !== width && width !== undefined) {
          resizeObserver.disconnect();
    
          a.value.textContent = a.value.textContent.concat('- some text - ');
    
          setTimeout(() => {
            resizeObserver.observe(element);
          }, 0);     
        }
        width = entries[0].contentRect.width; //<-- this needs to be outside the if(){...}
      });
    
      resizeObserver.observe(element);
    });
    </script>
    

    This is correct working code.