nuxt3: 如何在页面中间件中访问获取的数据

huangapple go评论63阅读模式
英文:

nuxt3: how to access fetched data in page middleware

问题

我正在处理一个Nuxt 3项目,关于我的一个文件中的语法问题有一个疑问。

(我想让它更加SEO友好,所以不使用pages/posts/[id].vue,而是使用pages/posts/[id]/[title].vue。)

以下是pages/posts/[id]/[title].vuesetup部分的代码:

type Post {
    title: string;
};

const route = useRoute();

const { data } = await useFetch(
    `/posts/${route.params.id}`
) as {
    data: Ref<Post>
};

definePageMeta({
    middleware: [
        (to: RouteLocationNormalized, from: RouteLocationNormalized) => {

            // 我想在这里访问获取到的数据
            if (to.params.title !== data.value.title) {
                navigateTo(`/posts/${data.value.id}/${data.value.title}`);
            }
        }
    ]
});

然而,当我运行代码时,我收到一个**500错误,消息是"data is not defined."** 我知道我可以在中间件中独立获取帖子数据,但这会导致重复请求,这不是理想的情况。

我该如何改进我的代码,使其工作并且只发送一次请求?

非常感谢任何人的帮助!

英文:

I'm working on a Nuxt 3 project, and I have a question about the syntax in one of my files.

(I want to make it more SEO-friendly, so instead of using pages/posts/[id].vue, I'm using pages/posts/[id]/[title].vue.)

Here's the code in the setup section of pages/posts/[id]/[title].vue:

type Post {
    title: string;
};

const route = useRoute();

const { data } = await useFetch(
    `/posts/${route.params.id}`
) as {
    data: Ref<Post>
};

definePageMeta({
    middleware: [
        (to: RouteLocationNormalized, from: RouteLocationNormalized) => {

            // I want to access the fetched data here
            if (to.params.title !== data.value.title) {
                navigateTo(`/posts/${data.value.id}/${data.value.title}`);
            }
        }
    ]
});

However, when I run the code, I receive a 500 error with the message "data is not defined." I know that I can fetch the post data in middleware independently, but it would result in duplicate requests, which is not ideal.

How can I improve my code to make it works and send the request only once?

Thanks a lot for anyone helps!

答案1

得分: 1

你需要存储数据,我对Nuxt还很陌生,今天也有同样的问题,不过我刚刚找到了解决方法。

在你的中间件中:

const $store = useNuxtApp()
$store.$requestData = data.value

然后,在你的页面中:

<script setup>
    const $store = useNuxtApp()
    console.log('data', $store.$requestData)
    const data = $store.$requestData;
</script>

当然,我对Nuxt(或JS框架一般)还很陌生,如果有更好的解决方案,欢迎提出,以防我漏掉了什么。

英文:

You'll need to store the data, I'm new to Nuxt and had the same question today and ended up figuring out a few minutes ago.

In your middleware:

const $store = useNuxtApp()
$store.$requestData = data.value

Then, in your page:

&lt;script setup&gt;

    const $store = useNuxtApp()
    console.log(&#39;data&#39;, $store.$requestData)
    const data = $store.$requestData;

&lt;/script&gt;

Of course I'm still very new to Nuxt (or JS frameworks in general), and any better solution would be welcome, in case I'm missing something here.

答案2

得分: 0

Here is the translated content:

使用[@joelod的答案](https://stackoverflow.com/a/76357173/10519069)和以下内容:
- [Reddit中的讨论**在SSR中使用Pinia与Firebase Composable**](https://stackoverflow.com/a/76357173/10519069)
- [GitHub问题**nuxtApp.call**](https://github.com/nuxt/nuxt/issues/14805#issue-1549639017)

这是解决方案

```js
import { useNuxtApp, callWithNuxt } from '#app';

// 在中间件中只获取一次帖子数据,而不是在外部获取
definePageMeta({
    middleware: [
        async (to: RouteLocationNormalized, from: RouteLocationNormalized) => {

            const nuxtApp = useNuxtApp();

            const { data: post } = await useFetch(
                `/posts/${to.params.id}`
            ) as {
                data: Ref<Post>;
            };

            await callWithNuxt(
                nuxtApp,
                () => {
                    nuxtApp.$requestData = post.value;
                }
            );
        }
    ]
});

const nuxtApp = useNuxtApp();
const route = useRoute();

const post: Ref<Post> = ref(nuxtApp.$requestData as Post);

if (to.params.title !== post.value.title) {
    navigateTo(`/posts/${post.value.id}/${post.value.title}`);
}

// 然后你可以在任何地方使用`post`数据
useSeoMeta({
    title: `${post.value.title} | My Blog`,
});

PS:

在中间件之外编写navigateTo()可能是更好的做法,因为当useFetch收到错误时,例如404 Not Found429 Too Many Requests,如果navigateTo()在中间件内部,则页面可能会出现[nuxt] A composable that requires access to the Nuxt instance was called outside of a plugin, Nuxt hook, Nuxt middleware, or Vue setup function的错误消息,因为你的template可能会使用post数据。


<details>
<summary>英文:</summary>

With [@joelod&#39;s answer](https://stackoverflow.com/a/76357173/10519069) and the followings:
- [the discuss in reddit: **USing Pinia with firebase composable in SSR**](https://stackoverflow.com/a/76357173/10519069)
- [the GitHub issue: **nuxtApp.call**](https://github.com/nuxt/nuxt/issues/14805#issue-1549639017)

Here is the solution:

```js
import { useNuxtApp, callWithNuxt } from &#39;#app&#39;;

// fetch the post data only once in middleware instead of the outside
definePageMeta({
    middleware: [
        async (to: RouteLocationNormalized, from: RouteLocationNormalized) =&gt; {

            const nuxtApp = useNuxtApp();

            const { data: post } = await useFetch(
                `/posts/${to.params.id}`
            ) as {
                data: Ref&lt;Post&gt;
            };

            await callWithNuxt(
                nuxtApp,
                () =&gt; {
                    nuxtApp.$requestData = post.value;
                }
            );
        }
    ]
});

const nuxtApp = useNuxtApp();
const route = useRoute();

const post: Ref&lt;Post&gt; = ref(nuxtApp.$requestData as Post);

if (to.params.title !== post.value.title) {
    navigateTo(`/posts/${post.value.id}/${post.value.title}`);
}

// then you can use the `post` data anywhere
useSeoMeta({
    title: `${post.value.title} | My Blog`,
});

PS:

Writing navigateTo() outside of the middleware may be a better practice because when useFetch received an error, such as 404 Not Found or 429 Too Many Requests, the page could get [nuxt] A composable that requires access to the Nuxt instance was called outside of a plugin, Nuxt hook, Nuxt middleware, or Vue setup function if navigateTo() is inside of the middleware, since your template may use the post data.

huangapple
  • 本文由 发表于 2023年5月29日 15:33:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/76355447.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定