Skip to content

Next.js 核心功能详解 (续)

1. 设置页面标题 (<Head> 组件)

问题: 如何为每个页面设置不同的浏览器标题 (<title>) 和其他的 <head> 标签(如 <meta>)?

解决方案: Next.js 提供了一个内置组件 <Head>,从 next/head 中导入。你可以在任何页面或组件中使用它,Next.js 会在服务端渲染时,将 <Head> 组件内的所有元素正确地渲染到最终 HTML 的 <head> 部分。

实现:

  1. 导入 Head 组件:

    javascript
    import Head from 'next/head';
  2. 在页面组件中使用:

    jsx
    // pages/index.jsx
    import Head from 'next/head';
    
    const HomePage = () => {
        return (
            <div>
                <Head>
                    <title>首页</title>
                    <meta name="description" content="这是我的首页" />
                </Head>
                <h1>我是首页内容</h1>
            </div>
        );
    };
    
    export default HomePage;
    jsx
    // pages/movies/index.jsx
    import Head from 'next/head';
    
    const MoviesPage = () => {
        return (
            <>  {/* 使用 Fragment 避免多余的 div */}
                <Head>
                    <title>电影页</title>
                </Head>
                <h1>我是电影页内容</h1>
            </>
        );
    };
    
    export default MoviesPage;

效果: 当在不同页面间导航时,浏览器的标签页标题会相应地改变。查看网页源代码,可以看到服务端已经将正确的 <title> 渲染到了 HTML 中。

2. 样式处理 (Styling)

Next.js 内置了对多种 CSS 方案的优秀支持。

2.1. 全局 CSS (Global CSS)

规则: 全局样式表必须pages/_app.js 文件中导入,在其他任何地方导入都会报错。

实现:

  1. 创建全局样式文件,例如 styles/global.css
    css
    /* styles/global.css */
    body {
        margin: 0;
        padding: 0;
        /* ...其他全局重置或基础样式... */
    }
    a {
        color: inherit;
        text-decoration: none;
    }
  2. pages/_app.js 中导入。
    jsx
    // pages/_app.js
    import '../styles/global.css'; // 直接导入
    
    function MyApp({ Component, pageProps }) {
        return <Component {...pageProps} />;
    }
    
    export default MyApp;

2.2. 组件级 CSS (CSS Modules)

规则: 要想实现样式的模块化(即样式只作用于当前组件,不污染全局),CSS 文件名必须遵循 [name].module.css 的命名约定。

实现:

  1. 为组件创建模块化 CSS 文件,例如 components/Header.module.css
    css
    /* components/Header.module.css */
    .header {
        height: 55px;
        line-height: 55px;
        background-color: black;
        color: white;
        padding: 0 30px;
    }
  2. 在组件中导入并使用。
    jsx
    // components/Header.jsx
    import styles from './Header.module.css'; // 导入 styles 对象
    
    export default function Header() {
        return (
            <div className={styles.header}> {/* 通过 styles 对象引用类名 */}
                {/* ...导航内容... */}
            </div>
        );
    }

效果: Next.js 会自动为 .header 类名生成一个唯一的哈希值(如 Header_header__12345),确保了样式的局部作用域。

2.3. 其他样式方案

Next.js 还原生支持:

  • Sass/SCSS: 只需安装 sass 依赖 (npm install sass),即可直接导入 .scss.sass 文件。

  • CSS-in-JS: 比如 styled-componentsemotion

  • styled-jsx: 一种内置的、类似于 Vue 中 <style scoped> 的方案,允许你在组件内部直接编写带作用域的 CSS。

    jsx
    function MyComponent() {
        return (
            <div>
                <p>只有这个 p 标签是红色的</p>
                <style jsx>{`
                    p {
                        color: red;
                    }
                `}</style>
            </div>
        );
    }

3. 静态资源 (Static Assets)

规则: Next.js 将项目根目录下的 public 文件夹约定为静态资源目录。该目录下的所有文件都可以通过根路径 / 直接访问。

实现:

  1. 将图片、字体、favicon.ico 等文件放入 public 文件夹。
    public/
    ├── logo.png
    └── favicon.ico
  2. 在代码中通过根相对路径引用它们。
    jsx
    // 在组件中引用 public/logo.png
    <img src="/logo.png" alt="My Logo" />

效果: 访问 http://localhost:3000/logo.png 可以直接看到图片。public 目录非常适合存放那些不需要经过 Webpack 处理的静态文件。