Nuxt 3如何实现带Payload的动态路由预渲染?
在Nuxt 3中替代Nuxt 2预渲染路由payload的实现方案
我在Nuxt 2里通过nuxt.config.js的generate async routes函数,借助Contentful的数据预渲染路由——先拉取所有相关Contentful数据,遍历生成路由的同时通过payload传递数据。但转到Nuxt 3后,找不到对应的实现方式:目前用prerender:routes钩子生成了路由,但这个钩子没有payload选项,导致页面拿不到正确的数据。
Nuxt 2 实现代码(nuxt.config.js)
generate: { fallback: true, crawler: false, async routes() { const courses = ( await fetchEntriesByContentType({ contentType: "courses" }) ).map((entry) => ({ route: `/courses/${entry.fields.slug}`, payload: entry, })); const jobs = ( await fetchEntriesByContentType({ contentType: "job" }) ).map((entry) => ({ route: `/jobs/${entry.fields.slug}`, payload: entry, })); return [...courses, ...jobs]; } }
Nuxt 3 当前实现(nuxt.config.js)
hooks: { 'prerender:routes': async function (ctx) { try { Promise.all([ client.getEntries({ content_type: "courses" }), client.getEntries({ content_type: "job" }) ]) .then(([courses, jobs]) => { for (const course of courses.items) { ctx.routes.add(`/courses/${course.fields.slug}/`); } for (const job of jobs.items) { ctx.routes.add(`/jobs/${job.fields.slug}/`); } }) } catch (error) { console.error('Error fetching data:', error); } } }
Nuxt 3 替代方案
Nuxt 3不再支持直接通过路由钩子传递payload,但可以通过两种方式实现类似效果:
1. 页面组件内直接获取数据(推荐)
在对应页面组件(如pages/courses/[slug].vue)中,使用useAsyncData或useFetch在预渲染/服务端阶段拉取对应数据:
<script setup> const route = useRoute(); const { data: course } = await useAsyncData(`course-${route.params.slug}`, async () => { const res = await client.getEntries({ content_type: "courses", 'fields.slug': route.params.slug }); return res.items[0]; }); </script>
预渲染时Nuxt会自动执行该逻辑,将数据注入静态页面,无需额外传递payload。
2. 利用nitro:prerender钩子存储数据(进阶)
如果需要在预渲染阶段提前准备好所有数据,可使用nitro:prerender钩子将数据存入应用配置,再在页面中读取:
// nuxt.config.js export default defineNuxtConfig({ hooks: { async 'nitro:prerender'({ routes, nuxt }) { // 拉取所有Contentful数据 const [coursesRes, jobsRes] = await Promise.all([ client.getEntries({ content_type: "courses" }), client.getEntries({ content_type: "job" }) ]); // 将数据存入应用配置 nuxt.options.appConfig.prerenderData = { courses: coursesRes.items, jobs: jobsRes.items }; // 添加预渲染路由 coursesRes.items.forEach(course => routes.add(`/courses/${course.fields.slug}`)); jobsRes.items.forEach(job => routes.add(`/jobs/${job.fields.slug}`)); } } });
页面中读取数据:
<script setup> const route = useRoute(); const appConfig = useAppConfig(); const course = appConfig.prerenderData.courses.find(c => c.fields.slug === route.params.slug); </script>
内容的提问来源于stack exchange,提问作者user2953989
相关产品推荐
相关产品推荐

