进阶
了解完语法之后,让我们一起在本地启动一个服务,开始 React 之旅。
安装 Node.js
React 是一个基于 JavaScript 的库,Node.js 是一个 JavaScript 运行环境,我们需要在本地安装 Node.js,才能运行 React 项目。
Node.js 的安装非常简单,只需要在官网下载安装包,然后一路下一步即可。
Node.js 官网 (opens in a new tab),安装时选择 LTS 版本即可。
安装完成后,打开命令行,输入 node -v
,如果能够输出版本号,说明安装成功。
安装 NPM
NPM 不需要刻意安装,Node.js 安装完成后,NPM 也就安装完成了。NPM 作为 Node.js 的包管理工具,我们可以通过 NPM 来安装 React。
打开命令行,输入 npm -v
,如果能够输出版本号,说明安装成功。
使用 React 框架
React 官方建议选择社区中流行的、由 React 驱动的框架。这些框架提供大多数应用和网站最终需要的功能,包括路由、数据获取和生成 HTML。当前,官方已经不推荐原来的 create-react-app
,而是推荐使用 Next.js
。接下来,我们就使用 Next.js
来创建一个 React 项目。
创建项目
打开一个空文件夹,打开 PowerShell.
输入以下命令:
npx create-next-app
它会让你填写一些项目:
What is your project named? my-app # 项目名称,随便填写
Would you like to use TypeScript? No / Yes # 是否使用 TypeScript,暂时不用,填写 No
Would you like to use ESLint? No / Yes # 是否使用 ESLint,暂时不用,填写 No
Would you like to use Tailwind CSS? No / Yes # 是否使用 Tailwind CSS,这个填写 Yes
Would you like to use `src/` directory? No / Yes # 是否使用 src 目录,我们这里不用,填写 No
Would you like to use App Router? (recommended) No / Yes # 是否使用 App Router,我们这里不用,填写 No
Would you like to customize the default import alias (@/*)? No / Yes # 是否自定义模块导入别名,我们这里不用,填写 No
创建完成后,会自动安装依赖,安装完成后,文件夹会有以下文件:
使用 VSCode 打开项目,可以看到项目的目录结构:
打开终端:
输入以下命令,启动项目:
npm run dev
在浏览器中打开 http://localhost:3000
,可以看到项目已经启动成功了。
npm 命令: npm 作为 Node.js 的包管理工具,也可以用于执行一些命令。因为 React 是一个框架,而浏览器是无法直接运行框架的代码的,最终需要编译为原生的 HTML、CSS 和 JavaScript,才能在浏览器中运行。所以,我们需要使用 npm 来执行一些命令,比如启动项目、编译项目等。让我们不妨打开 package.json
文件,看一下里面的内容:
这里声明的一些 scripts
,就是我们可以通过 npm 来执行的命令。比如,我们可以通过 npm run dev
来启动项目,通过 npm run build
来编译项目。
当你在终端中输入 npm run dev
时,实际上执行的是 next dev
命令,这个命令是 Next.js 提供的,用于启动项目。在这背后,Next.js 会自动帮我们编译项目,然后启动一个服务器,让我们可以在浏览器中访问项目。
你可以将项目中的 pages/index.js
文件中的内容全部删除,然后修改为以下内容,然后保存,浏览器会自动刷新,你就可以看到修改后的效果了。
export default function Home() {
return (
<div>
<h1>Hello World</h1>
</div>
);
}
你可以看到下面的效果:
外部组件
一个页面可能由很多组件组成,合理地拆分组件,可以让代码更加清晰,便于维护。
如下图中,我们可以将页面拆分为 LOGO
、NavBar
、Article
、Footer
四个组件。
我们可以将组件放在 components
目录下,然后在页面中引入。
分别创建组件:
components/logo.js
export default function LOGO() {
return (
<div>
<h1>Stutuer</h1>
</div>
);
}
注意,每个组件的名称首字母必须大写,否则会报错。
且每个单独的组件必须有一个根元素,否则也会报错。比如下面的代码就会报错:
export default function LOGO() {
return (
<h1>Stutuer</h1>
<p>这是一个网站</p>
);
}
必要要使用一个根元素包裹起来:
export default function LOGO() {
return (
<>
<h1>Stutuer</h1>
<p>这是一个网站</p>
</>
);
}
这里使用了一个空标签 <>
,它是一个占位符,不会在页面中显示。
每个组件需要用 export default
导出,才能在其他地方引入。
components/NavBar.js
export default function NavBar() {
return (
<div style={{ display: "flex", justifyContent: "space-between" }}>
<a href="/">Home</a>
<a href="/about">About</a>
<a href="/contact">Contact</a>
</div>
);
}
components/article.js
export default function Article() {
return (
<div>
<h1>Article</h1>
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit.
Quisquam, voluptatum. Quisquam, voluptatum. Quisquam, voluptatum.
Quisquam, voluptatum. Quisquam, voluptatum. Quisquam, voluptatum.
</p>
</div>
);
}
components/footer.js
export default function Footer() {
return (
<div>
<h1>Footer</h1>
</div>
);
}
然后在 pages/index.js 中引入:
import LOGO from "../components/logo";
import NavBar from "../components/NavBar";
import Article from "../components/article";
import Footer from "../components/footer";
然后就可以在页面中使用组件了:
export default function Home() {
return (
<div>
<LOGO />
<NavBar />
<Article />
<Footer />
</div>
);
}
运行项目,可以看到被四个组件组装起来的页面:
import LOGO from "../components/logo"; import Footer from "../components/footer"; import Article from "../components/article"; import NavBar from "../components/NavBar"; export default function Home() { return ( <div> <div style={{ display: "flex", justifyContent: "space-between" }}> <LOGO /> <NavBar /> </div> <Article /> <Footer /> </div> ); }
当然,你也可以在组件中使用其他组件,比如在 NavBar
组件中使用 LOGO
组件:
import LOGO from "../components/logo";
export default function NavBar() {
return (
<div style={{ display: "flex", justifyContent: "space-between" }}>
<LOGO />
<a href="/">Home</a>
<a href="/about">About</a>
<a href="/contact">Contact</a>
</div>
);
}
那么我们只需要在 Index 页面中引入 NavBar
组件即可,LOGO
组件会作为 NavBar
的子组件被渲染出来。
import Footer from "../components/footer"; import Article from "../components/article"; import NavBar from "../components/NavBar"; export default function Home() { return ( <div> <NavBar /> <Article /> <Footer /> </div> ); }
静态资源
在 Next.js 中,我们可以在 public
目录下存放静态资源,比如图片、视频、音频等。
你可以在 public
目录下创建一个 images
目录,然后将图片放在里面。比如有一张图片 logo.png
,那么我们可以在页面中这样引入:
<img src="/images/logo.png" />
你可能注意到,这里的路径是 /images/logo.png
,而不是 ../public/images/logo.png
,这是因为 Next.js 会将 public
目录下的文件映射到根路径 /
下,所以我们可以直接使用 /images/logo.png
。正因为如此,你可以在浏览器导航栏输入 http://localhost:3000/images/logo.png
来正确访问到这张图片。
路由
Next.js 采用了约定式路由,即页面的路径和文件路径是一致的。你会发现,我们在创建工程时,会自动生成 pages
目录,这个目录下的每个文件(除了 _app.js
和 _document.js
)或文件夹下的文件都会被映射为一个路由。
例如,我们在 pages
目录下创建一个 about.js
文件,那么这个文件就会被映射为 /about
路由。
import LOGO from "../components/logo";
import Footer from "../components/footer";
import NavBar from "../components/NavBar";
export default function About() {
return (
<div>
<div style={{ display: "flex", justifyContent: "space-between" }}>
<LOGO />
<NavBar />
</div>
<div>
This is the about page
</div>
<Footer />
</div>
);
}
import LOGO from "../components/logo"; import Footer from "../components/footer"; import NavBar from "../components/NavBar"; export default function About() { return ( <div> <div style={{ display: "flex", justifyContent: "space-between" }}> <LOGO /> <NavBar /> </div> <div> This is the about page </div> <Footer /> </div> ); }
我们修改一下 NavBar
组件,添加一个 About
的链接:
import LOGO from "./logo";
import Link from "next/link";
export default function NavBar() {
return (
<div style={{ display: "flex", justifyContent: "space-between" }}>
<LOGO />
<Link href="/">
<a>Home</a>
</Link>
<Link href="/about">
<a>About</a>
</Link>
</div>
);
}
注意,我们在这里使用了 Link
组件,这是 Next.js 提供的一个组件,用于实现客户端路由。由于它是一个组件,所以我们需要在 NavBar
组件中引入它。
import Link from "next/link";
然后我们就可以在 NavBar
组件中使用它了,使其包裹 a
标签,这样点击 a
标签时就会触发路由跳转。
<Link href="/about">
<a>About</a>
</Link>
import LOGO from "./logo"; import Link from "next/link"; export default function NavBar() { return ( <div style={{ display: "flex", justifyContent: "space-between" }}> <LOGO /> <Link href="/"> <a>Home</a> </Link> <Link href="/about"> <a>About</a> </Link> </div> ); }
点击 About
链接,你会发现页面跳转了到了 http://localhost:3000/about
,并且页面内容也发生了变化。点击 Home
链接,页面又跳转回了 http://localhost:3000/
。
样式
在 Next.js 中,我们可以使用 CSS 模块化来管理样式。CSS 模块化是一种将 CSS 作用域限制在组件内部的技术,这样就可以避免全局污染,同时也可以避免组件之间的样式冲突。
例如,在这里,我们将 about.js 删除,然后创建 About
文件夹,再在里面创建 index.js
文件,并创建 index.module.css
文件。
在 index.js
中添加下面的内容:
import LOGO from "../../components/logo";
import Footer from "../../components/footer";
import NavBar from "../../components/NavBar";
import styles from "./index.module.css";
export default function About() {
return (
<div>
<div style={{ display: "flex", justifyContent: "space-between" }}>
<LOGO />
<NavBar />
</div>
<div className={styles.container}>
This is the about page
</div>
<Footer />
</div>
);
}
然后在 index.module.css
中添加下面的内容:
.container {
font-size: 20px;
color: white;
background: #282c34;
padding: 20px;
}
import LOGO from "../../components/logo"; import Footer from "../../components/footer"; import NavBar from "../../components/NavBar"; import style from "./index.module.css"; export default function About() { return ( <div> <div style={{ display: "flex", justifyContent: "space-between" }}> <LOGO /> <NavBar /> </div> <div className={style.container}> This is the new about page </div> <Footer /> </div> ); }
可以看到样式已经生效了。