此bounty已结束。此问题的答案有资格获得+200声望奖励。赏金宽限期14小时后结束。chojnicki希望引起更多关注这个问题。
我正在使用Suspense,并在页面上获取异步数据。在初始化回退加载指示器是可见的,但在切换页面时,我会保留当前页面的内容,直到新页面准备就绪+nprogress
条,因此网站的行为更像SSR。也有过渡之间,但它并不重要的问题。
而且效果很好。问题是当我的页面有子页面(嵌套的路由),也与Suspense。当我在像/demo/demo1
这样的嵌套页面上导航到主页时,/demo
模板的内容保持原样,但子页面demo1
的内容消失了。我需要保留嵌套的Suspense,直到父Suspense准备就绪。有什么想法吗
我尽可能地简化代码。我在根应用程序和页面上使用相同的<RouterView>
代码。
<RouterView v-slot="{ Component }">
<template v-if="Component">
<Suspense>
<component :is="Component" />
<template #fallback>
Loading...
</template>
</Suspense>
</template>
</RouterView>
以下是现场再现:https://stackblitz.com/edit/vitejs-vite-gg6kqo?file=src/pages/demo/demo1.vue(没有nprogress,只是在页面之间等待1 s)。
繁殖步骤:
1.点击“关于”-“主页”停留,直到“关于”准备好,然后“关于”出现-工作正常。
1.点击“Demo”-出现“demo”根页面,出现嵌套“demo/demo 1”路由的回退-工作正常。
1.点击“主页”-“演示/演示1”的内容立即消失。
2条答案
按热度按时间wtlkbnrh1#
我不会说这是最好的答案,但在我看来,为了让
<Suspense>
工作,它的子组件必须是一个异步组件。在这种情况下,<RouterView>
被呈现为非异步组件(即使其子组件是异步组件),因此根<Suspense>
不会等待<RouterView>
中的<Suspense>
。作为一种解决方法,我认为我们可以缓存组件,这样当路由器被更改时(第三种情况),它看起来就不会消失。
我的缓存方法是在
demo.vue
文件中添加这个<script setup>
:然后将同一文件中的
<RouterView>
修改为:{{ cacheComponent(Component) }}
行将在组件被渲染时缓存它(这样使用是因为<RouterView>
在其插槽被挂载时没有回调)。CachedComponent.value = Component || CachedComponent.value;
行将更新CachedComponent值,如果有一个新的Component不是falsy。如果它是falsy(意味着它还没有被挂载或不再被挂载),它将呈现组件的先前的最新缓存版本。我知道这是黑客,但在我看来,这是一个非常简单的解决办法。This is the forked stackblitz如果你感兴趣的话
lhcgjxsq2#
当您有嵌套路由时,它在复杂的项目中根本不起作用,正如您所注意到的那样,它可以很好地在单个级别上进行路由。
我为此奋斗了一段时间,尝试了许多组合,发现嵌套的悬念被打破了,这与被动用于路由器组件的
key
周围的功能故障有关,我尝试手动设置这一点,产生了各种结果和其他无法修复/恼人的问题,包括使用keep-alive
。不能使用
async setup
真的很烦人和不幸,特别是在尝试API调用之前协商其他承诺时挂起,我特别喜欢代码的整洁程度。我不得不接受async
watch
,其中我设置了一个loading = ref(true)
状态,并将其传递给一个自定义的加载状态组件 Package 器,该 Package 器将I/O阻止内容并在内容主体中显示加载进度。如果你想的话,你也可以在那里拍过渡。
我还在考虑重新推导加载 Package 器和加载引用的重复,方法是将其移动到托管子
router-view
的父组件,并在子页面中使用emit
来切换加载。我还没有尝试过这个,需要确保转换到其他页面时的初始状态为真。