Before rendering the page for a given route, I want to first get the necessary data synchronously. Ideally I'd like to get the data in the page component, but I'm not opposed to doing it in the router file. I've read and tried various approaches, but part of the challenge comes from the fact that there are multiple ways to build components, and the use of certain features varies.
In my case I use Composition API and
语法构建单文件组件。 Vue Router 文档链接讨论了“导航前获取”,其中我可以访问 beforeRouteEnter
或 beforeRouteUpdate
,但这是使用选项 API 显示的。他们确实有 Composition API 的页面,提到我可以使用 onBeforeRouteUpdate
,但它使用 setup()
函数。我想无论如何我都会尝试使用
:
<script setup> import { onBeforeRouteUpdate } from 'vue-router' onBeforeRouteUpdate(() => { console.log('onBeforeRouteUpdate') }) </script>
但是,这不会执行。我尝试过的最接近的方法是使用 beforeEnter
防护来获取路由器中的数据,并将数据设置到 meta
属性上,然后可以在组件中的路由实例上访问该属性: p>
beforeEnter: (to, from, next) => { fetch('https://pokeapi.co/api/v2/pokemon/ditto') .then(res => res.json()) .then(res => { to.meta.pokemon = res; next(); }); }
但是有了这个,文档中指出, beforeEnter
仅在输入路由时触发。参数更改不会重新触发此问题,这意味着我必须在组件中的路线上设置一个观察程序。我还不如将所有这些逻辑都放在组件本身中。
我似乎找不到一个好的方法来做到这一点,但我可能忽略了一些事情。如果有人有一些指示或建议,我将不胜感激。提前致谢。
P粉5462579132023-11-18 12:39:56
First of all, beforeRouteUpdate
is only triggered when the actual route is updated, but does not go to another component/page like the official tells here.
An example of what might trigger a lifecycle hook is
<button @click="$router.push({ hash: `#${Math.floor(Math.random() * 10)}` })"> random hash </button>
onBeforeRouteLeave
Works perfectly, as you would expect, when moving from one page to another.
For the original question, you could implement some kind of router middleware like Nuxt does . This way you wait for
the HTTP call and only then allow actual navigation. So it's almost possible to create a block navigation effect.
I'm not sure how to write it using the Composition API, but I know it works perfectly with the Options API (there are plenty of blog posts available). setup
itself runs in it's own life cycle way and I imagine a lot of things are pretty tricky.
TLDR: In my opinion, a good router middleware page wrapper (like layout) is the perfect combination in your case. There you can set up an observer for quite a few pages at the same time.
But everything depends on how you want to organize yourself and structure your code.
The skeleton screen gives a faster feel than blocking, but in general you can also use prefetch< /a> (also shipped with Nuxt by default) to get some hints and maybe Certain resources are required before loading them. (Other tricks in the same domain to speed up your network requests)
P粉5459565972023-11-18 11:49:37
There is a solution - use top level await - https://vuejs.org/api/sfc-script-setup.html#top-level-await
Just wrap the RouterView component in a Suspense component as shown below - https://vuejs.org/guide/built-ins/suspense.html#combining-with-other-components( Don't use unnecessary components)
The only thing to note is that the "loading screen" will be visible on the initial request.
I made a small demo for you so you can try it out - https://github.com/ileue/vue-top-level-await-demo