Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

using scrollMonitor.recalculateLocations() after a DOM change - how to? #76

Open
steappe opened this issue Jan 29, 2018 · 4 comments
Open

Comments

@steappe
Copy link

steappe commented Jan 29, 2018

I'm using Vue.js in a project where I have a scroll container and its child elements.

In the scroll container:

  mounted: function () {
    this.monitor = scrollMonitor.createContainer(this.$el);
  },

  updated: function () {
    this.monitor.recalculateLocations();
  }

In the child elements:

  mounted () {
    this.watcher = this.monitor.create(this.$el);
    this.inViewport = this.watcher.isInViewport;

    this.watcher.visibilityChange(() => {
      this.inViewport = this.watcher.isInViewport;
    });
  },

  beforeDestroy () {
    this.watcher.destroy();
  }

The scroll container passes the scroll monitor to its children through a Vue property.

This works perfectly fine, until an element is moved from one position in the list to another. This is causing the associated DOM element to be moved in the scroll container, and the updated Hook function is called. This Hook function invokes monitor.recalculateLocations() to have the children watchers recalculate their locations and triggers events. But this is not happening (if the element is moved from a position where it is not visible to a position where it is visible in the scroll container, no event is fired), and I would like to understand why.

Example:

  • Div for element 1 (in viewport)
  • Div for element 2 (in viewport)
  • etc.
  • Div for element n (not in viewport)

The element n is moved to top, resulting in the following changes in the DOM:

  • Div for element n (in viewport)
  • Div for element 1 (in viewport)
  • etc.
  • Div for element n-1 (not in viewport)

The Div for element n is now visible in it's parent scroll container. However, when the scrollMonitor.recalculateLocations() is called, the watcher created for element n does not trigger the visibility change callback.

@stutrek
Copy link
Owner

stutrek commented Jan 29, 2018

I don't know much about how Vue works, but I suspect it has something to do with the virtual DOM swapping elements.

Is there a way to get Vue to give you the DOM element that currently represents the Vue component? If you get it right before your error is it the same as when your component was created?

I didn't make any of these so I can't speak to their quality, but there are a few packages that connect Vue and the scroll monitor.

@steappe
Copy link
Author

steappe commented Jan 30, 2018

I've played around with these packages, and unless I'm wrong the first two ones only work when the body is scrolled. The third one does more or less what I'm doing in my project.

According to what I can see in Chrome, the Vue's updated Hook is invoked after the div element has been moved in the real DOM.

I've tried what they suggest in their documentation:

updated: function () {
  this.$nextTick(function () {
    // Code that will run only after the
    // entire view has been re-rendered
  })
}

I call scrollMonitor.recalculateLocations() in that function, but this is not triggering the visibility change callback set on the watcher of the moved element.

@stutrek
Copy link
Owner

stutrek commented Jan 30, 2018

Is the first one the only one that's incorrect or is the first one out of the viewport also incorrect?

@steappe
Copy link
Author

steappe commented Jan 31, 2018

When I invoke scrollMonitor.recalculateLocations(), I would say both. When I scroll, I get visibility change notifications about elements that are not in the viewport, as if the div element had not been moved.

When I do not invoke scrollMonitor.recalculateLocations(), the notifications are OK when I scroll. It's just that I don't receive a visibility change notification at the very moment the div element is moved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants