admin管理员组

文章数量:1205745

I'm a bit surprised that in order to listen to changes on elements dimensions (not window Object) we have to use a new interface called ResizeObserver. While it seems to do the job pretty well; it seems a bit of a departure from other element related events that can be consumed by just adding a listener.

Take for example adding an event listener to listen for the mouseover event

document.querySelector('#ele').addEventListener('mouseover', callback);

Why not simply add a new listener to the resize event on the elements?

document.querySelector('#ele').addEventListener('resize', callback);

Is it to avoid conflicts with the window resize event? If so, why not just call it differently

document.querySelector('#ele').addEventListener('elementResize', callback);

I'm aware it is easy to create a helper method to simplify the usage of the ResizeObserver. Something like that can be as simple to use as the original addEventListener approach

export const getResizeObserver = ( ele, onResize ) => {
  let obs;

  const observerInterface = {
    stop: () => { obs.unobserve( ele ); obs.disconnect() },
  };

  obs = new ResizeObserver( entries => {
    for ( const entry of entries ) {
      onResize && onResize( entry.contentRect );
    }
  } );

  obs.observe( ele );

  return observerInterface;
};

// usage to add the listener
const obs = getResizeObserver(document.querySelector('#ele'), callback);
// later to remove the listener
obs.stop();

In any case, Is there any reason, besides just api preferences and the fact that several elements can share the observer instance, that makes the ResizeObserver approach better than the addEventListener approach?

I'm a bit surprised that in order to listen to changes on elements dimensions (not window Object) we have to use a new interface called ResizeObserver. While it seems to do the job pretty well; it seems a bit of a departure from other element related events that can be consumed by just adding a listener.

Take for example adding an event listener to listen for the mouseover event

document.querySelector('#ele').addEventListener('mouseover', callback);

Why not simply add a new listener to the resize event on the elements?

document.querySelector('#ele').addEventListener('resize', callback);

Is it to avoid conflicts with the window resize event? If so, why not just call it differently

document.querySelector('#ele').addEventListener('elementResize', callback);

I'm aware it is easy to create a helper method to simplify the usage of the ResizeObserver. Something like that can be as simple to use as the original addEventListener approach

export const getResizeObserver = ( ele, onResize ) => {
  let obs;

  const observerInterface = {
    stop: () => { obs.unobserve( ele ); obs.disconnect() },
  };

  obs = new ResizeObserver( entries => {
    for ( const entry of entries ) {
      onResize && onResize( entry.contentRect );
    }
  } );

  obs.observe( ele );

  return observerInterface;
};

// usage to add the listener
const obs = getResizeObserver(document.querySelector('#ele'), callback);
// later to remove the listener
obs.stop();

In any case, Is there any reason, besides just api preferences and the fact that several elements can share the observer instance, that makes the ResizeObserver approach better than the addEventListener approach?

Share Improve this question asked Jan 4, 2018 at 2:43 roy riojasroy riojas 2,4763 gold badges28 silver badges30 bronze badges
Add a comment  | 

2 Answers 2

Reset to default 12

There is a discussion in this PR in which the W3C technical architecture group tries to define when to use the Observer pattern over the EventTarget. The output of this discussion is documented here, and I'm quoting the first statement:

In general, use EventTarget and notification Events, rather than an Observer pattern, unless an EventTarget can’t work well for your feature.

The advantages of using an Observer pattern over EventTarget are as follows:

  1. Instances can be customized at observation time or at creation time. The constructor for an Observer, or its observe() method, can take options allowing authors to customize what is observed for each callback. This isn’t possible with addEventListener().

  2. It’s easy to stop listening on multiple callbacks using the disconnect() or unobserve() method on the Observer object.

  3. You have the option to provide a method like takeRecords(), which immediately fetches the relevant data instead of waiting for an event to fire.

  4. Because Observers are single-purpose, you don’t need to specify an event type.

Talking specifically about the ResizeObserver, in my opinion:

  • The 2nd and 4th points aren't too relevant. It doesn't add or take anything crucial, and I think that the resize event would be a much better match here.

  • It still doesn't implement the takeRecords() method, so the 3d point irrelevant

It leaves us with the ability to customize it at the creation and observation time and allows changing these customization APIs later on without changing the Event model.

Also, there are possible performance issues or an unavoidable recursion, but I didn't find any measurements or explanations regarding them.

This was proposed, but Chrome decided to ship this using the Observer model, seemingly mostly because it was 10x faster than an implementation based on events https://groups.google.com/a/chromium.org/forum/#!topic/blink-dev/z6ienONUb5A

Now why that’s true, I don’t know.

本文标签: