[React] Next.js
Next.js 产品级的 React 框架 - 中文开发入门教学
这里先了解下是个神马东西~
与 [React] Review 的不同在于,这个重在实践~
https://nextjs.org/docs/getting-started
操作步骤
-
安装 Node.js
https://nodejs.org/zh-cn/download/
-
包管理器方式
https://nodejs.org/zh-cn/download/package-manager/
-
建立 NextJS 工程
貌似next 13版本又发生了较大的升级。
本教程的Node也需要是14版本。
# 建立工程 $ npx create-next-app@11.1.2 myweb # TypeScript 版本 $ npx create-next-app@latest --typescript myweb_t # 启动开发模式 $ cd myweb $ npm run dev >http://localhost:3000/
# 文件路由?添加一个文件,根据文件名自动添加路由。
# 增加一个页面 About.js $ nano About.js ... >http://localhost:3000/About # 编译生产模式 $ npm run build $ ls -a $ ls .next $ npm start >http://localhost:3000/
-
添加 bootstrap CSS
在“入口”文件_app.js中增强head的部分,添加一条 for css bootstrap.
-
服务器前端
以前的多页面站点是在服务端渲染的,输出到浏览器时已经有了完整的骨架( html ),这样爬虫抓到时可以分析页面标题,内容等等,做 seo 容易,那时的技术栈是 jsp,php 等等。现在流行的前端框架在这方面是开了倒车,一个空的骨架,一个很大的 js,抓到浏览器以后才开始渲染完整的页面,爬虫就很为难了,因为它没法执行 js 啊,此外,白屏时间也是由于前端渲染带来的问题。于是又有了服务端渲染,让渲染这一步再回到服务端,在服务端模拟浏览器环境,给 react 和 vue 等框架一个可执行的上下文,就是为了提前得到完整的 html。前端就是这么扯蛋。
// 原来设置在了./api的位置
export default function handler(req, res) { res.status(200).json({ name: 'John Doe' }) }
路由 Routes
文件路由
http://localhost:3000/news/top
http://localhost:3000/news/
== 以下是react的形态 ==
next.js 省略以下文件。
// App.js
import PageHome from './components/PageHome'; import PageAbout from './components/PageAbout'; import PageNews from './components/PageNews';
function App() { return ( <div> <Header></Header> <div className="p-4"> <Route path="/" exact> <PageHome></PageHome> </Route> <Route path="/news"> <PageNews></PageNews> </Route> <Route path="/about"> <PageAbout></PageAbout> </Route> </div> </div> ); }
路由参数
-
news/id
import React from "react"; import { useRouter } from "next/dist/client/router"; const newsid = () => { const router = useRouter(); console.log(router.pathname); console.log(router.query); return ( <React.Fragment> <h1>newsid</h1> <hr /> {router.pathname && ( <h3>{router.pathname}</h3> )} {router.query.id && ( <h3>{router.query.id}</h3> )} </React.Fragment> ) } export default newsid;
-
blog/tag/id
import React from "react"; import { useRouter } from "next/dist/client/router"; const newsid = () => { const router = useRouter(); console.log(router.pathname); console.log(router.query); return ( <React.Fragment> <h1>newsid</h1> <hr /> {router.pathname && ( <h3>{router.pathname}</h3> )} {router.query.tag && ( <h3>{router.query.tag}</h3> )} {router.query.id && ( <h3>{router.query.id}</h3> )} </React.Fragment> ) } export default newsid;
http://127.0.0.1:3000/isbn/aa/bb/cc
变量slug代表的对象 反映了 isbn 后的部分。可以拥有“编程”。(实用)
import React from "react"; import { useRouter } from "next/dist/client/router"; const slug = () => { const router = useRouter(); console.log(router.pathname); console.log(router.query); return ( <React.Fragment> <h1>newsid</h1> <hr /> {router.pathname && ( <h3>{router.pathname}</h3> )} {router.query.slug && ( <h3>{router.query.slug.join(',')}</h3> )} </React.Fragment> ) } export default slug;
-
-
Routes - 链接路径传递参数
-
如下这么搞,为何不直接使用:pathname: "/news/001"? 而是采用这种JSON of query的形式?
以下包含了“链接 link”与“按钮 router.push”两种点击方式。
import Head from 'next/head' import Link from 'next/link' import { useRouter } from 'next/dist/client/router' export default function Home() { const router = useRouter(); const btn_click = () => { router.push({ pathname: '/news/[id]', query: { id: '001' } }) } return ( <div> <Head> <title>Create Next App</title> <meta name="description" content="Generated by create next app" /> <link rel="icon" href="/favicon.ico" /> </Head> <main> <h1>Next.js</h1> <hr /> <Link href="/About" >About</Link> <hr /> <Link href={{ pathname: "/news/[id]", query: { id: '001' } }}>新闻001</Link><br /> <Link href={{ pathname: "/news/[id]", query: { id: '002' } }}>新闻002</Link><br /> <Link href={{ pathname: "/news/[id]", query: { id: '003' } }}>新闻003</Link> </main> <hr /> <button className="btn btn-success" onClick={btn_click}>新闻001</button> </div> ) }
404 页面
默认的名字。
import React from "react"; const Page404 = () => { return ( <React.Fragment> <h1>Page404</h1> </React.Fragment> ) } export default Page404;