如何用Gatsby File System Route API为数组每一项生成独立页面
实现方案
Gatsby File System Route API默认绑定数组类型字段时,会把整个数组的值拼接后作为路径生成单个页面,要实现为数组内每个元素生成独立页面,有两种常用的可落地方案:
方案一:使用gatsby-node.js手动创建页面(最推荐,灵活度高)
这种方式不需要改现有数据结构,直接自定义生成规则即可:
- 在项目根目录的
gatsby-node.js文件中添加以下逻辑,先查询全量Airtable数据,再遍历数组元素生成页面:
exports.createPages = async ({ graphql, actions }) => { const { createPage } = actions // 查询所有Airtable数据 const result = await graphql(` query { allAirtable { edges { node { data { Projects Locations } } } } } `) // 遍历每个节点的Projects数组,为每个元素生成页面 result.data.allAirtable.edges.forEach(({ node }) => { node.data.Projects.forEach(project => { // 格式化路径为小写、替换空格等特殊字符,避免非法路径 const slug = project.toLowerCase().replace(/\s+/g, '-') createPage({ path: `/projects/${slug}`, // 指向你提前写好的项目详情模板文件 component: require.resolve("./src/templates/project.js"), // 给模板传递参数,可直接在模板的pageContext中获取,也可用于GraphQL查询变量 context: { projectName: project, }, }) }) // 如果Locations字段也需要生成独立页面,重复上面的遍历逻辑即可 node.data.Locations.forEach(location => { const slug = location.toLowerCase().replace(/\s+/g, '-') createPage({ path: `/locations/${slug}`, component: require.resolve("./src/templates/location.js"), context: { locationName: location, }, }) }) }) }
- 编写对应的模板文件,比如
src/templates/project.js,示例逻辑如下:
const ProjectPage = ({ pageContext }) => { // 直接从pageContext拿到当前项目名 const { projectName } = pageContext return <div>当前项目:{projectName}</div> } export default ProjectPage
如果需要查询关联的其他数据,也可以在模板中使用页面级GraphQL查询,把projectName作为查询变量过滤数据即可。
方案二:派生独立节点适配File System Route API
如果你更习惯用文件路由的方式生成页面,可以先为数组的每个元素生成独立的Gatsby节点:
- 在
gatsby-node.js的onCreateNode钩子中,检测到Airtable节点时,遍历它的Projects数组,为每个元素创建单独的AirtableProject类型节点 - 之后在
src/pages目录下创建{AirtableProject.slug}.js的路由文件,即可自动为每个项目生成独立页面
注意事项
- 如果多条Airtable记录包含同一个项目名,可根据业务需求决定是生成同一个页面聚合所有关联记录,还是在路径中加唯一标识区分
- 生成路径时建议统一格式化字符,避免大小写、特殊字符导致的路径错误
内容的提问来源于stack exchange,提问作者Lone Wallaby
相关产品推荐
相关产品推荐

