4

I'm aware of mounted and created being life cycle hooks and have tried them. I've also tried using $nextTick within mounted and that does not work to get an accurate render either. I am currently trying to access some data out of a dom node after the initial render. Here's the pertinent part of my code:

mounted() {
  console.log(this.$el.getBoundingClientRect().top);
},

This is giving me incorrect data. However, using this code:

mounted() {
  setTimeout(() => {
    console.log(this.$el.getBoundingClientRect().top);
  }, 1000)
},

Does net me the correct data. The threshold is about ~700-900 ms before I start getting the correct data.

Question 1

Why is the lifecycle invoke when everything hasn't fully rendered?

Question 2

Does it have to do with sibling components that haven't quite mounted yet that might be pushing dimensions?

Question 3

Is there a solution, an event that I can hook into that basically says, 'everything on the page has rendered'.

I don't love the setTimeout solution that I came up with for obvious reasons.

Andrew Kim
  • 2,479
  • 3
  • 15
  • 36

2 Answers2

1

Due to the fact that things render asynchronously, you may not be able to be sure that the position isn't going to change. You will likely need to get the position every time something updates. You can do that with a custom directive, whose update function will be called when things update.

Here's a little demo:

new Vue({
  el: '#app',
  data: {
    ht: 100,
    top: null
  },
  directives: {
    bounding(el, binding, vnode) {
      vnode.context[binding.expression] = el.getBoundingClientRect().top;
    }
  },
  mounted() {
    let times = 5;
    const i = setInterval(() => {
      this.ht += 10;
      if (--times < 1) {
        clearInterval(i);
      }
    }, 1000);
  }
});
<script src="//unpkg.com/vue@latest/dist/vue.js"></script>
<div id="app">
  <div :style="{height: `${ht}px`}">Hi</div>
  <div v-bounding="top">{{top}}</div>
</div>
Roy J
  • 37,999
  • 5
  • 58
  • 88
0

Q1: The lifecycle hooks are only concerned about the instance itself and not the rest of the dom. Hence - the rest of the page can be pending while the component is fully mounted.

Q2: Same as Q1.

Q3: You could use this:

document.addEventListener("DOMContentLoaded", function(event) {
    console.log(this.$el.getBoundingClientRect().top);
});

For an more indepth answer: $(document).ready equivalent without jQuery

Edit

You should use this instead:

window.addEventListener("load", function(event) {
    console.log(this.$el.getBoundingClientRect().top);
});

I forgot about the external resources. DOMContentLoaded is fired when the dom is loaded ie. html. load is fired after the external resources have been loaded. Further reading: https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onload

Rudi Ørnhøj
  • 171
  • 1
  • 11