this.$refs 或文档在 mounted() 中不可见,除非我使用 setTimeout
this.$refs or document are not visible in mounted() unless I use setTimeout
我遇到了一个奇怪的问题。我认为 $refs
可从 mounted()
生命周期
但是如果我尝试直接 log
它是我未定义的对象:
mounted() {
// logs undefined
console.log(
this.$refs.tabsMenu
)
}
等待 1 毫秒后,它已定义,我可以获取对象
mounted() {
setTimeout(() => {
// logs the object
console.log(
this.$refs.tabsMenu
)
}, 1) // <-- just 1ms!
}
对此有什么想法吗?
我的(简化)模板如下所示
<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>
那是因为mounted()
不保证DOM渲染完成。您需要等待 this.$nextTick()
:
mounted() {
this.$nextTick(() => {
console.log(this.$refs.tabsMenu)
});
}
setTimeout(callback, 1)
对您有效的原因是因为您实质上将回调(在您的代码中,访问引用并将其记录到控制台)推迟到调用堆栈的末尾,也就是当DOM 会完成渲染。
如果您熟悉使用 async/await,您也可以这样做:
async mounted() {
await this.$nextTick();
console.log(this.$refs.tabsMenu);
}
更新:您的 ref
元素似乎实际上包含在另一个 VueJS 组件 <baseComponent>
中。在这种情况下,在 parent/consuming 组件上监听 this.$nextTick()
是不够的,因为它不能保证内部组件被挂载 和 渲染。
如果您仍然需要使用这种方法,那么我唯一的建议是确保内部 <baseComponent>
在挂载并且其 DOM 已呈现时发出某种事件,例如通过发出 ready
事件:
// Inside baseComponent
mounted() {
this.$nextTick(() => {
this.$emit('ready');
});
}
然后,在你的父组件中,你可以这样监听事件:
<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>
然后在组件的代码中:
methods {
onReady: function() {
console.log(this.$refs.tabsMenu);
}
}
我遇到了一个奇怪的问题。我认为 $refs
可从 mounted()
生命周期
但是如果我尝试直接 log
它是我未定义的对象:
mounted() {
// logs undefined
console.log(
this.$refs.tabsMenu
)
}
等待 1 毫秒后,它已定义,我可以获取对象
mounted() {
setTimeout(() => {
// logs the object
console.log(
this.$refs.tabsMenu
)
}, 1) // <-- just 1ms!
}
对此有什么想法吗?
我的(简化)模板如下所示
<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>
那是因为mounted()
不保证DOM渲染完成。您需要等待 this.$nextTick()
:
mounted() {
this.$nextTick(() => {
console.log(this.$refs.tabsMenu)
});
}
setTimeout(callback, 1)
对您有效的原因是因为您实质上将回调(在您的代码中,访问引用并将其记录到控制台)推迟到调用堆栈的末尾,也就是当DOM 会完成渲染。
如果您熟悉使用 async/await,您也可以这样做:
async mounted() {
await this.$nextTick();
console.log(this.$refs.tabsMenu);
}
更新:您的 ref
元素似乎实际上包含在另一个 VueJS 组件 <baseComponent>
中。在这种情况下,在 parent/consuming 组件上监听 this.$nextTick()
是不够的,因为它不能保证内部组件被挂载 和 渲染。
如果您仍然需要使用这种方法,那么我唯一的建议是确保内部 <baseComponent>
在挂载并且其 DOM 已呈现时发出某种事件,例如通过发出 ready
事件:
// Inside baseComponent
mounted() {
this.$nextTick(() => {
this.$emit('ready');
});
}
然后,在你的父组件中,你可以这样监听事件:
<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>
然后在组件的代码中:
methods {
onReady: function() {
console.log(this.$refs.tabsMenu);
}
}