一、Next.js 的介绍
这是一个用于生产环境的 React 框架,Next.js 为您提供生产环境所需的所有功能以及最佳的开发体验:包括静态及服务器端融合渲染、 支持 TypeScript、智能化打包、 路由预取等功能无需任何配置。
二、快速搭建项目
使用 create-next-app 进行项目的搭建
// 安装create-next-app
npm install -g create-next-app
// 新建dext-demo项目
npx create-next-app next-demo
// 按照提示启动项目
cd next-demo
yarn dev
Next.js 是围绕着 页面(pages) 的概念构造的。一个页面(page)就是一个从 pages
目录下的 .js
、.jsx
、.ts
或 .tsx
文件导出的 React 组件。
页面(page) 根据其文件名与路由关联。例如,pages/about.js
被映射到 /about
。甚至可以在文件名中添加动态路由参数。
三、Next的使用
1 路由跳转:标签跳转、编程跳转
标签跳转:通过 Link
组件可以启用客户端的路由切换。
假设有一个jump页面,需要从主页跳转至jump页面,再从jump页面返回主页
pages/index.js
import React from 'react'
import Link from 'next/link'
export default function Home() {
return (
<div>
<h1>首页</h1>
<Link href="/jump"><a>跳转jump页面</a></Link>
</div>
)
}
pages/jump.js
import Link from 'next/link'
import { withRouter } from 'next/router'
function Jump({router}){
return (
<div>
<div>{router.query.name} page</div>
<Link href="/"><a>返回首页</a></Link>
</div>
)
}
export default withRouter(Jump)
假设跳转页面时需要传递部分参数,Next允许用户传递query参数
<Link href="/jump?name=jump"><a>跳转jump页面</a></Link>
Link标签的href属性也可以接受一个对象
<Link href={{pathname: '/jump', query: {name: 'jump'}}}><a>跳转jump页面</a></Link>
编程跳转:可以使用Router.push()方法进行跳转
pages/index.js
import React from 'react'
import Link from 'next/link'
import Router from 'next/router'
export default function Home() {
const jump = () => {
Router.push('/jump?name=jump1')
// Router.push({
// pathname:'/jump1',
// query: {
// name: 'jump1'
// }
// })
}
return (
<div>
<h1>首页</h1>
<button onClick={jump}>跳转jump页面</button>
</div>
)
}
2 路由的事件
我们可以使用router.events.on去监听路由事件的发生
- routeChangeStart :当路由开始发生改变时触发
- routeChangeComplete:路由变化完成触发
- routeChangeError:当路由发生变化时产生错误触发
- beforeHistoryChange:当修改浏览器的history之前触发
- hashChangeStart:
- hashChangeComplete:
import React from 'react'
import Link from 'next/link'
import Router from 'next/router'
export default function Home() {
Router.events.on('routeChangeStart', (...arg) => {
console.log('routeChangeStart', ...arg);
});
Router.events.on('routeChangeComplete', (...arg) => {
console.log('routeChangeComplete', ...arg);
});
Router.events.on('routeChangeError', (...arg) => {
console.log('routeChangeError', ...arg);
});
Router.events.on('beforeHistoryChange', (...arg) => {
console.log('beforeHistoryChange', ...arg);
});
Router.events.on('hashChangeStart', (...arg) => {
console.log('hashChangeStart', ...arg);
});
Router.events.on('hashChangeComplete', (...arg) => {
console.log('hashChangeComplete', ...arg);
});
return (
<div>
<h1>首页</h1>
<Link href="/jump?name=jump"><a>跳转jump页面</a></Link>ss
<br/>
<Link href='#hash'><a>hash变化</a></Link>
</div>
)
}
3 next/head
Next.js 暴露了一个内置组件,用于将 HTML 标签添加到页面的 head
中。
最初写页面时发现head标签中是没有title,meta等标签,使用Next的head标签可以让我们自定义head,可以有更加友好的SEO操作。
components/head.js
import Head from 'next/head';
export default function MyHead() {
return (
<div>
<Head>
<title>liaoxin</title>
<meta charSet='utf-8'></meta>
</Head>
</div>
)
}
pages/header.js
import MyHead from '../components/head';
export default function Header() {
return (
<div>
<MyHead></MyHead>
<div>header</div>
</div>
)
}
4 获取数据
Next.js 有两种预渲染的形式:
- 服务端渲染(SSR):访问xxx路由之前,向服务器请求数据,把请求的数据和HTML加工直接返回前台显示,下次访问同一个路由地址的时候,还需要做相同的操作,如果访问的用户数很多,服务器的压力就会很大。
- 静态生成(SSG):访问xxx路由之前,向服务器请求数据,将请求的数据和HTML加工生成真正的xxx.html 文件,这样下次访问同一个路由地址的时候,直接返回静态页面,提高加载速度,减小服务器的压力,以达到性能优化的目的。
出于性能考虑,相对服务器端渲染,Next.js 更 推荐 使用 静态生成 。 CDN 可以在没有额外配置的情况下缓存静态生成的页面以提高性能。但是,在某些情况下,服务器端渲染可能是唯一的选择。
获取数据方法 | 静态化 | 异步 | 只能在pages文件夹下 | 作用 | 服务端请求 |
---|---|---|---|---|---|
getStaticProps | 是 | 是 | 是 | 请求数据 | 是http(非XMLHttpRequest) |
getStaticPaths | 是 | 是 | 是 | 生成动态路由 | 是 |
getServerSideProps | 否 | 是 | 是 | 请求数据 | 是 |
1.getServerSideProps(context):实现服务端渲染的核心,将数据和页面整合在一起。
- params: 接受getStaticPaths()返回的动态路径,方便请求动态数据
- req: HTTP 请求对象
- res: HTTP响应对象
- query: 查询字符串
getServerSideProps的返回值是一个对象,对象中有一个key值为props,并且props作为该组件的props
import React from 'react'
import fetch from 'node-fetch'
export default function Case(props) {
const { data } = props
console.log('props data', data)
return (
<div>
<ul>
{
data.map((item) => {
return <li key={item.name}>{`姓名: ${item.name} 性别: ${item.sex}年龄: ${item.age}`}</li>
})
}
</ul>
</div>
)
}
export const getServerSideProps = async () => {
const res = await fetch('http://localhost:5000/list');
let data = await res.json()
console.log('data', data)
return {
props: {
data: data.data
}
}
}
在Chrome开发工具中的Network可以发现并没有list这个请求,这是因为数据不是从浏览器客户端发起请求获取的。
可以看到组件props中使用的数据在控制台打印出来了,这个代码是Next.js后台服务器,也就是Node环境执行的,http://localhost:5000/list 这个请求是Node服务器发起的,拿到数据后会放在页面中,然后把整合好的数据和页面返回浏览器。
2.getStaticProps(context)
- params: 接受getStaticPaths()返回的动态路径,方便请求动态数据
如: http://localhost:5000/list
getStaticProps的返回值是一个对象,对象中有一个key值为props,并且props作为该组件的props
import React from 'react'
import fetch from 'node-fetch'
export default function Case(props) {
const { data } = props
console.log('props data', data)
return (
<div>
<ul>
{
data.map((item) => {
return <li key={item.name}>{`姓名: ${item.name} 性别: ${item.sex} 年龄: ${item.age}`}</li>
})
}
</ul>
</div>
)
}
export const getStaticProps = async () => {
const res = await fetch('http://localhost:5000/list');
let data = await res.json()
console.log('data', data)
return {
props: {
data: data.data
}
}
}
在项目build过程中会发现在控制台有打印如下信息,因为Next.js需要把数据写在静态页面,所以需要先把数据拿到,然后会直接把数据放到页面中替换好生成静态文件。
在.next/pages/list.html可以看到整个页面结构
<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><meta name="next-head-count" content="2"/><link rel="preload" href="/_next/static/css/120f2e2270820d49a21f.css" as="style"/><link rel="stylesheet" href="/_next/static/css/120f2e2270820d49a21f.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/_next/static/chunks/polyfills-a54b4f32bdc1ef890ddd.js"></script><script src="/_next/static/chunks/webpack-672781b4256b347cef75.js" defer=""></script><script src="/_next/static/chunks/framework-64eb7138163e04c228e4.js" defer=""></script><script src="/_next/static/chunks/main-655ad0ce567efa01caa9.js" defer=""></script><script src="/_next/static/chunks/pages/_app-2767ddbc84b83c8aece3.js" defer=""></script><script src="/_next/static/chunks/pages/list-36f0c233c3f71d7df129.js" defer=""></script><script src="/_next/static/dgI7Ei5v8D8G2DWDomy57/_buildManifest.js" defer=""></script><script src="/_next/static/dgI7Ei5v8D8G2DWDomy57/_ssgManifest.js" defer=""></script></head><body><div id="__next"><div><ul><li>姓名: liaoxin 性别: female 年龄: 18</li><li>姓名: liaoliao 性别: female 年龄: 19</li><li>姓名: xinxin 性别: female 年龄: 19</li></ul></div></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{"data":[{"name":"liaoxin","sex":"female","age":18},{"name":"liaoliao","sex":"female","age":19},{"name":"xinxin","sex":"female","age":19}]},"__N_SSG":true},"page":"/list","query":{},"buildId":"dgI7Ei5v8D8G2DWDomy57","isFallback":false,"gsp":true,"scriptLoader":[]}</script></body></html>
四、Next.js构建与运行
// 执行
yarn build
在.next文件夹中存放Next.js构建过程中的所有文件
将文件放在服务器上面就可以访问了。
- 本文作者: étoile
- 版权声明: 本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。转载请注明出处!