'How to save local values from inside onMounted hook - Vue 3

how do I save assigned values from inside onMounted hook in Vue 3? My intention of saving the width and height values is so that can use to manipulate the values inside a custom-directive outside of the setup function later on.

I realised that it is only possible manipulating inside the onMounted and using watch see if there is a change to the value. But even so, after assigning the values, it is still undefined.

Is using Vuex the way to go for my current solution?

Because I can only access DOM properties inside onMounted hook and not anywhere else.

<template>
  <div class="outer">
    <div class="container">
      <div>
        <div class="border">
          <img
            id="image"
            ref="image"
            src="@/assets/1.jpg"
            class="image"
          />
        </div>
      </div>
    </div>
  </div>
</template>

<script lang="ts">
import { ref, defineComponent, onMounted, watch } from "vue";

const widthVal = ref<number>()
const heightVal = ref<number>()

export default defineComponent({
  setup() {
    const image = ref<HTMLElement | null>(null)

    onMounted(() => {
      if (image.value) {
        widthVal.value = image.value.offsetWidth;
        heightVal.value = image.value.offsetHeight;

        console.log('width: ', widthVal.value)
        console.log('height: ', heightVal.value)
      }
    })

    watch([widthVal, heightVal], (newVal, oldVal) => {
      widthVal.value = newVal[0];
      heightVal.value = newVal[1];

      console.log(widthVal.value)
      console.log(heightVal.value)
    })  

    // becomes undedefined 
    console.log('width: ', widthVal.value)

    return { image }
  }
});
</script>

<style>
p {
  color: yellow;
}
.outer {
  margin: 1em;
  display: flex;
  justify-content: center;
  height: 100vh;
}
.container {
  background: rgb(98, 98, 98);
  border-radius: 5px;
  width: 950px;
  height: 650px;
  padding: 1em;
  overflow: hidden;
  font-family: "Trebuchet Ms", helvetica, sans-serif;
}
img {
  width: 950px;
  height: 650px;

  /* remove margins */
  margin-left: -18px;
  margin-top: -18px;
}
</style>


Solution 1:[1]

If you inspect widthVal inside setup() and not inside the watch or onMounted function it gets called BEFORE the values are assigned cause assignments inside setup happen even before the beforeCreate hook. See: lifecycle hooks

EDIT:

If you really want to use widthVal/heightVal inside setup I'd recommend using it within a function (or a watcher, whatever you need) and calling that inside onMounted after you initialized widthVal/heightVal. E.g.:

const doSomethingElse = () => {
  // Use widthVal and heightVal here...    
}

onMounted(() => {
  widthVal.value = newVal[0];
  heightVal.value = newVal[1];

  doSomethingElse();
})  
...

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1