I'm having a weird issue. I thought that $refs
were available from mounted()
life-cycle
But if I try to log
directly it's the object i get undefined:
mounted() {
// logs undefined
console.log(
this.$refs.tabsMenu
)
}
And after waiting 1ms it's defined and I can get the object
mounted() {
setTimeout(() => {
// logs the object
console.log(
this.$refs.tabsMenu
)
}, 1) // <-- just 1ms!
}
Any thoughts about this?
My (simplified) template looks like this
<template>
<div>
<baseContainer>
<ul ref="tabsMenu" id="tabs-menu" class="flex-inline flex w-full">
<li>Home</li>
<!-- many more items -->
<li>Contact</li>
</ul>
</baseContainer>
</div>
</div>
That is because mounted()
does not guarantee that the DOM has finished rendering. You will need to wait for this.$nextTick()
:
mounted() {
this.$nextTick(() => {
console.log(this.$refs.tabsMenu)
});
}
The reason why setTimeout(callback, 1)
works for you is because you are essentially deferring the callback (which is in your code, accessing the reference and logging it to console) to the end of the callstack, which is when the DOM would've finished rendering.
If you're familiar with using async/await, you can also do this:
async mounted() {
await this.$nextTick();
console.log(this.$refs.tabsMenu);
}
Update: It seems like your ref
element is actually contained in another VueJS component <baseComponent>
. In this case, listening to this.$nextTick()
on the parent/consuming component is not sufficient, because it doesn't guarantee the inner component is mounted and rendered.
If you still need to use this approach, then my only advice is to ensure that the inner <baseComponent>
emits some kind of event when it is mounted and its DOM has been rendered, e.g. by emitting a ready
event:
// Inside baseComponent
mounted() {
this.$nextTick(() => {
this.$emit('ready');
});
}
Then, in your parent component, you can listen to the event as such:
<baseContainer v-on:ready="onReady">
<ul ref="tabsMenu" id="tabs-menu" class="flex-inline flex w-full">
<li>Home</li>
<!-- many more items -->
<li>Contact</li>
</ul>
</baseContainer>
Then in the component's code:
methods {
onReady: function() {
console.log(this.$refs.tabsMenu);
}
}