Ton*_*bet 3 javascript lifecycle settimeout vue.js
我有一个奇怪的问题。我认为$refs可以从mounted()生命周期中获得
但如果我尝试log直接它是我得到未定义的对象:
mounted() {
// logs undefined
console.log(
this.$refs.tabsMenu
)
}
Run Code Online (Sandbox Code Playgroud)
等待 1ms 后它就被定义了,我可以得到对象
mounted() {
setTimeout(() => {
// logs the object
console.log(
this.$refs.tabsMenu
)
}, 1) // <-- just 1ms!
}
Run Code Online (Sandbox Code Playgroud)
对此有什么想法吗?
我的(简化的)模板如下所示
<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>
Run Code Online (Sandbox Code Playgroud)
那是因为mounted()不保证 DOM 已经完成渲染。您需要等待this.$nextTick():
mounted() {
this.$nextTick(() => {
console.log(this.$refs.tabsMenu)
});
}
Run Code Online (Sandbox Code Playgroud)
之所以setTimeout(callback, 1)对你有用是因为你本质上将回调(在你的代码中,访问引用并将其记录到控制台)推迟到调用堆栈的末尾,也就是 DOM 完成渲染的时候。
如果您熟悉使用 async/await,也可以这样做:
async mounted() {
await this.$nextTick();
console.log(this.$refs.tabsMenu);
}
Run Code Online (Sandbox Code Playgroud)
更新:看起来您的ref元素实际上包含在另一个 VueJS 组件中<baseComponent>。在这种情况下,侦听this.$nextTick()父/消费组件是不够的,因为它不能保证内部组件已安装和渲染。
如果您仍然需要使用这种方法,那么我唯一的建议是确保内部<baseComponent>在安装并且其 DOM 已渲染时发出某种事件,例如通过发出事件ready:
// Inside baseComponent
mounted() {
this.$nextTick(() => {
this.$emit('ready');
});
}
Run Code Online (Sandbox Code Playgroud)
然后,在您的父组件中,您可以监听该事件,如下所示:
<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>
Run Code Online (Sandbox Code Playgroud)
然后在组件的代码中:
methods {
onReady: function() {
console.log(this.$refs.tabsMenu);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3940 次 |
| 最近记录: |