Menu
CoddyTech

动态元数据

本课属于 Coddy React 学习旅程的“Next.js 基础”单元。第 15 课,共 47 课。

metadata 对象是常量,因此无法用于动态路由:app/dishes/[slug]/page.jsx 会在每个 URL 下显示不同的菜品,每个菜品都需要自己的标题。

为此,请改为导出一个函数:

export async function generateMetadata({ params }) {
    const { slug } = await params;
    return { title: DISHES[slug].name };
}

它会获取页面所获取的相同 params(这是一个 promise,所以你需要 await 它),并返回与 metadata 对象相同的结构。在同一个文件中二选一,不要同时使用两者。

标题模板

每个页面的标题都重复显示网站名称,时间久了会让人厌烦。布局可以传递一个模式,而不是一个普通字符串:

// app/layout.jsx
export const metadata = {
    title: {
        default: 'Coddy Eats',
        template: '%s | Coddy Eats',
    },
};
  • default:未设置标题的页面使用的标题
  • template:已设置标题的页面使用的模式;页面标题会放在 %s 的位置

因此,返回 title: 'Margherita' 的页面最终会在标签页中显示为 Margherita | Coddy Eats,而没有设置任何内容的主页则会显示为 Coddy Eats。在布局中写一次品牌名称即可。

challenge icon

挑战

中等

目前每个菜品页面的标签页都显示 Coddy Eats。为每个页面设置各自的标题。

在 app/dishes/[slug]/page.jsx 中,添加一个导出的 async 函数,名为 generateMetadata,它需要:

  1. 接收 { params },并等待它以获取 slug
  2. 返回 { title: DISHES[slug].name }

app/layout.jsx 中已经设置了模板 '%s | Coddy Eats',因此 /dishes/margherita 的标题最终应为 Margherita | Coddy Eats。看一下布局文件,你不需要修改它。

亲手试试

import './globals.css';

export const metadata = {
    title: {
        default: 'Coddy Eats',
        template: '%s | Coddy Eats',
    },
};

export default function RootLayout({ children }) {
    return (
        <html lang="en">
            <body>
                {children}
            </body>
        </html>
    );
}
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

Next.js 基础中的所有课