我正在开发一个 Vue3/Vite Typescript 项目,使用
<Suspense>
在加载异步子组件时显示加载状态 #fallback 模板。这就像一个魅力。
但是我想在我的
<Suspense #default>
DOM 结构中拥有一个/多个元素的引用(例如,为一些漂亮的动画添加 IntersectionObserver
)。
我知道,当触发
onMounted()
钩子时,“目标”引用仍然未定义,因为当所有 static 内容准备就绪时(当异步组件仍在加载时;“加载器”引用返回 <div class="loader">
时,就会发生这种情况)
)。 Suspense 提供了 onResolve()
钩子,该钩子在加载 #default 模板中包含的所有异步组件后触发。
仍然“目标”引用未定义(“加载器”引用返回 null - 这没关系,因为它不再显示)。
测试:如果我删除
Introsection
(随着异步资源加载),<Suspense>
会直接解析(在onMounted()
之前),并且“目标”引用直接在<section>
钩子中返回引用的onMounted()
(在onResolve()
钩子两个引用均未定义)。
我做错了什么?感谢任何有用的提示/解决方案。
我的代码(缩写):
import IntroSection from '@/components/IntroSection.vue'
import { useTemplateRef, onBeforeUpdate, onUpdated, onMounted, ref } from 'vue'
const target = ref<Element>() // or useTemplateRef('target')
const loader = ref<Element>()
const animate = ref<boolean>(true)
onMounted(() => {
console.log('onMounted')
console.log(target.value)
console.log(loader.value)
})
onBeforeUpdate(() => {
console.log('onBeforeUpdate')
})
onUpdated(() => {
console.log('onUpdated')
})
function onPending() {
console.log('onPending...')
}
function onResolve() {
console.log('onResolve...')
console.log(target.value)
console.log(loader.value)
}
function onReject() {
console.log('onReject')
}
</script>
<template>
<Suspense :onPending="onPending" :onResolve="onResolve" :onReject="onReject">
<template #default>
<div>
<!-- Spacer Section -->
<section class="header_padding">
<div class="container">
<div class="row title"></div>
</div>
</section>
<!-- End Spacer Section -->
<!-- Intro Section with async asset loading -->
<IntroSection>
<div class="row title">
<h1 class="header_headline_style_2">
HEADLINE
</h1>
<p>
<br />
Some Text here
</p>
<br />
</div>
</IntroSection>
<!-- End Intro Section -->
<!-- Service Section -->
<section ref="target">
<div v-if="animate" class="nf-item spacing">
<div class="box_module_1">
<div class="box_module_2">
<h2 class="h2_box">TITLE</h2>
<p>TEXT</p>
</div>
<div class="box_module_2">
<RouterLink to="/text" class="btn">
BUTTONTEXT
</RouterLink>
</div>
</div>
</div>
</section>
<!-- End Service Section -->
</div>
</template>
<template #fallback>
<!-- Preloader -->
<section id="preloader">
<div class="loader" id="loader" ref="loader">
<div>Loading...</div>
<div class="loader-img"></div>
</div>
</section>
<!-- End Preloader -->
</template>
</Suspense>
</template>
要在加载异步组件后访问
ref
组件中的 <Suspense>
,请使用 nextTick
挂钩中的 onResolve
函数来确保 DOM 已更新。确保您的 ref
已正确分配给预期元素。使用 console.log
中的 onResolve
进行调试可以帮助验证 ref
的时间和可用性。这种方法有助于管理组件的异步特性及其对 Vue 反应系统的影响。
import { nextTick } from 'vue';
function onResolve() {
nextTick(() => {
console.log(target.value); // Now, target should be defined
});
}