admin管理员组

文章数量:1331435

Why the ResizeObserver class always execute the handler at the first observe()?

Try execute the code below on Chrome' dev tool:

(new ResizeObserver(() => console.log('resize detected'))).observe($0)

You will see the log printed immediately after you apply it, even if you didn't do any size change.

I need the resize observer that only executes the handler on resize.
Is there any hack/options to tweak it?

let disableObserver = false;

const obs = new ResizeObserver(() => {
   if (!disableObserver) {
      console.log('resize detected');
   }
});

// the hack below doesn't work:
disableObserver = true;
obs.observe(someElement);
disableObserver = false;

Why the ResizeObserver class always execute the handler at the first observe()?

Try execute the code below on Chrome' dev tool:

(new ResizeObserver(() => console.log('resize detected'))).observe($0)

You will see the log printed immediately after you apply it, even if you didn't do any size change.

I need the resize observer that only executes the handler on resize.
Is there any hack/options to tweak it?

let disableObserver = false;

const obs = new ResizeObserver(() => {
   if (!disableObserver) {
      console.log('resize detected');
   }
});

// the hack below doesn't work:
disableObserver = true;
obs.observe(someElement);
disableObserver = false;
Share edited May 29, 2021 at 19:12 Brian Tompsett - 汤莱恩 5,89372 gold badges61 silver badges133 bronze badges asked May 29, 2021 at 11:51 Heyyy MarcoHeyyy Marco 7632 gold badges13 silver badges27 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 7

Tested in different browsers and the reported behaviour is consistent - observer callback is called when observer() is called.

I've checked the specification, it says:

  • Observation will fire when watched Element is inserted/removed from DOM.
  • Observation will fire when watched Element display gets set to none.
  • Observations do not fire for non-replaced inline Elements.
  • Observations will not be triggered by CSS transforms.
  • Observation will fire when observation starts if Element is being rendered, and Element’s size is not 0,0.

I guess initial call is because of Element being rendered.

Each element can be added to a Set to skip initial call. Something like this:

let entriesSeen = new Set(); // set of entries to skip initial resize call

const obs = new ResizeObserver((entries) => {
    for (let entry of entries) {
        if (!entriesSeen.has(entry.target)) {
            // do nothing during initial call
            // just mark element as seen
            entriesSeen.add(entry.target);
        } else {
            console.log('resize detected');
            console.log(entry.target);
        }
    }
});

obs.observe(someElement);

I wrote Wrapper for build-in ResizeObserver which reacts only on sizeChanging and ignores hiding and displaying.

    class ResizeObserverWrapper {

    _lastWidth;
    _lastHeight;

    observe(htmlElement, onSizeChanged) {

        new ResizeObserver(entries => {
            if (entries != undefined && entries.length > 0) {
                const newWidth = entries[0].target.clientWidth;
                const newHeight = entries[0].target.clientHeight;


                if (newWidth != undefined && newWidth > 0
                    && newHeight != undefined && newHeight > 0
                ) {
                    let dimensionChanged = newWidth != this._lastWidth && this._lastWidth > 0
                        || newHeight != this._lastHeight  && this._lastHeight > 0 ;
                    this._lastHeight = newHeight;
                    this._lastWidth = newWidth;
                    if (dimensionChanged) {
                        onSizeChanged();
                    }
                }
            }
        }).observe(htmlElement);
    }
}

usage example:

new ResizeObserverWrapper().observe(yourRootElement.querySelector('.some-css-class'), () => console.log("It is resized"));

本文标签: htmlJavascript ResizeObserver is triggered unexpectedStack Overflow