Vueer
Vueer

Reputation: 1512

How to understand the mounted() function in Vue.Js with v-for

I try to understand how the mounted hook works on Vue.js. If I understand correctly, the mounted function is called when all DOM elements are rendered. So in this scenario, I will have access to the DOM elements with document.getElementById or this.$el.somenthing.

Is this right?

But why I get the following behavior? Lets say I have the following structure:

mounted() {
  this.buildTextTargetWidth();
},
methods: {
  buildTextTargetWidth() {
    console.log(document.getElementsByClassName('typographyTextPreview')); // Empty HTML-Collection. But, curiously, when I open the array in the console, there is the right element.
    console.log(document.getElementsByClassName('typographyTextPreview')[0]); // Undefined
  },
}

So far so good. The result is undefined. But for my understanding it should not!

Lets try to add some async stuff to wait 500ms:

mounted() {
  this.buildTextTargetWidth();
},
methods: {
  async buildTextTargetWidth() {
    await new Promise(r => setTimeout(r, 500));
    console.log(document.getElementById('test')); // The element is there
  },
}

Now the element is there!

But why I have to wait other 500ms to get the DOM data if the mounted() is calling after the DOM is ready? It makes no sense for me.

By the way: The element typographyTextPreview which I try to call is embedded inside a v-for. Could this be the reason for this behavior? If yes, how could I wait until the v-for is ready?

--EDIT--

I wanted to create this topic as clean and simple as possible. But here I add additional data from the component, for example the entire for loop where the element typographyTextPreview is included:

<div ref="builderLayer" class="vconf-create-builder column" :class="getColumnLength">
  <div class="vconf-create-builder-layers" :key="layersKey">
      <div v-for="layer of getLayers" class="vconf-create-builder-layer" :key="layer.uid" :style="{ background: 'url(' + getLayerImage(layer) + ') center / contain no-repeat' }">
        <template v-for="tile of layer.data">
          <!-- <VueDragResize :key="tile.uid" v-if="tile.type=='typography'" :parentLimitation="true" :isActive="true" :x="calculatePositionX(tile)" :y="calculatePositionY(tile)" :w="tile.editBoxWidth" :h="tile.editBoxHeight" @resizestop="updateTypoBoxSize($event, layer, tile)" @dragstop="updateTypoBoxPosition($event, layer, tile)">
            <h2 class="typographyTextPreview" :style="{'font-size':calculateFontSize(tile) + 'px', color: tile.fontColor}">{{tile.text ? tile.text : "Please enter an initial text in the settings"}}</h2>
          </VueDragResize> -->
          <div v-if="tile.type=='typography'" class="container" :key="tile.uid">
            <div class="target" :style="buildTextTargetStyle(tile)">
              <h2 id="test" class="typographyTextPreview" :style="{color: tile.fontColor}">{{tile.text ? tile.text : "Please enter an initial text in the settings"}}</h2>
            </div>
            <Moveable
              className="moveable"
              :target="['.target']"
              :keepRatio="true"
              :throttleResize="1"
              :bounds=' {"left":0,"top":0, "right": clientWidth, "bottom": clientHeight}'
              :origin="true"
              :snappable="true"
              :zoom="1"
              :draggable="true"
              :scalable="true"
              :rotatable="true"
              @drag="onDrag($event, tile)"
              @scale="onScale($event, tile)"
              @rotate="onRotate($event, tile)"
            />
          </div>
        </template>          
      </div>
  </div>
</div>

Upvotes: 0

Views: 828

Answers (1)

Nicola Spadari
Nicola Spadari

Reputation: 735

From the docs:

A component is considered mounted after:
All of its synchronous child components have been mounted (does not include async components or components inside trees).
Its own DOM tree has been created and inserted into the parent container. Note it only guarantees that the component's DOM tree is in-document if the application's root container is also in-document.

If you need to wait for DOM changes, I suggest you to use the nextTick utility, which waits for the DOM to be updated. More details here

Upvotes: 2

Related Questions