Next.js
是什么?
Next.js 是一个轻量级的 React 服务端渲染应用框架。有了它我们可以简单轻松的实现React的服务端渲染,从而加快首屏打开速度,也可以作SEO(收索引擎优化了)。
Next.js官方文档
最初
在没有Next.js的时候,用React开发需要配置很多繁琐的参数,如Webpack配置,Router配置和服务器端配置等….
如果需要作SEO,要考虑的事情就更多了,怎么样服务端渲染和客户端渲染保持一致就是一件非常麻烦的事情,需要引入很多第三方库。但有了Next.js,这些问题都解决了,使开发人员可以将精力放在业务逻辑上!
优点
- 搭建轻松
- 自带数据同步 SSR
- 丰富的插件
- 灵活的配置
搭建
- 手动配置
- 使用
create-next-app
脚手架配置
- 下载所用到的依赖
npm i react react-dom next
- 修改package.json
1 2 3 4 5 6
| "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "dev":"next", "build":"next build", "start": "next start" },
|
1.手动搭建
1 2 3 4 5 6
| function Index() { return ( <div>Hello Next.js</div> ) } export default Index
|
无需引入React就可以使用
2.脚手架
- 全局安装
npm i -g create-next-app
- 创建基础项目
npx create-next-app 项目名字
npx create-next-app next-create
项目大致结构如上,正常都知道是干什么的。
注:.eslintrc.json
文件是规范书写格式的一个第三方包
Next中的路由
在Next中pages文件夹就相当于路由集合,比如说,首页是index.js
,而如果url地址变成:3000/jspang.js
那么其就会进入jspang.js
文件。如果是多层的,那么路径就会变成:3000/blog/nextBlog.js
1.导航式跳转
- 新建两个页面
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| import Link from 'next/link' export default () => ( <> <div>jspang - A页面</div> <Link href='/'> <a>返回首页</a> </Link> </> )
import Link from 'next/link' export default () => ( <> <div>jspang - B页面</div> <Link href='/'> <a>返回首页</a> </Link> </> )
|
- 编写首页
1 2 3 4 5 6 7 8 9 10 11
| import React from 'react' import Link from 'next/link'
const Home = () =>( <> <div>我是首页</div> <div><Link href='/jspangA'><a>去jspangA页面</a></Link></div> <div><Link href='/jspangB'><a>去jspangB页面</a></Link></div> </> ) export default Home
|
注意点
2.编程式跳转
使用Router方法可以实现跳转页面
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| import React from 'react'; import Link from 'next/link'; import Router from 'next/router';
const Home = () =>{ function gotoA() { Router.push('/jspangA') } return ( <> <div>我是首页</div> <div><Link href='/jspangA'><a>去jspangA页面</a></Link></div> <div><Link href='/jspangB'><a>去jspangB页面</a></Link></div> <div> <button onClick={gotoA}>jspangA</button> </div> </> ) } export default Home
|
3.传参
路由式传参
query传参
将参数放在url进行传递
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| import React from 'react' import Link from 'next/link'
const Home = () =>{
return ( <> <div>我是首页</div> <div> <Link href="/chuancan?name=张三"> <a>跳转</a> </Link> // 第二种写法👇👇👇 <Link href={{pathname:'/chuancan',query:{name:'李四'}}}> <a>李四</a> </Link> </div> </> )
} export default Home
import React from 'react' import {withRouter} from 'next/router'; import Link from 'next/link'
const Chuancan = ({router})=>{ return ( <> <div>{router.query.name}</div> <Link href='/'><a>返回首页</a></Link> </> ) }
export default withRouter(Chuancan)
|
编程式传参
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| import React from 'react' import Link from 'next/link' import Router from 'next/router'
const Home = () =>{
function goto(){ Router.push({ pathname:'/chuancan', query:{ name:'张三' } }) } return ( <> <div>我是首页</div> <div> <Link href="/chuancan?name=张三"> <a>跳转</a> </Link> </div> <div> <button onClick={goto}>点击跳转并携带参数</button> </div> </> )
} export default Home
|
Next中的组件
在components文件下创建jspang.js
组件
1 2 3 4 5 6 7 8
| export default ({children})=> { return ( <button> {children} </button> ) }
|
在首页文件中导入
1 2 3 4 5 6 7 8
| import Jspang from '../components/jspang' export default function Home() { return ( <div> <Jspang>测试按钮组件</Jspang> </div> ) }
|
路由钩子事件
- routeChangeStart 路由发生变化之前
- routeChangeComplete 路由发生变化之后
- beforeHistoryChange Next.js全部都用History模式
- routeChangeError 路由发生错误时,404不算
- hashChangeStart Hash路由切换之前
- hashChangeComplete Hash路由切换完成
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
| import React from 'react' import Link from 'next/link' import Router from 'next/router'
const Home = () =>{
Router.events.on('routeChangeStart',(...argus)=>{ console.log('1.routeChangeStart,路由开始变化,参数为:',...argus); }) Router.events.on('routeChangeComplete',(...argus)=>{ console.log('2.routeChangeComplete,路由变化结束,参数为:',...argus); }) Router.events.on('beforeHistoryChange',(...argus)=>{ console.log('3.beforeHistoryChange,参数为:',...argus); }) Router.events.on('routeChangeError',(...argus)=>{ console.log('4.routeChangeError,路由发生错误时,参数为:',...argus); }) Router.events.on('hashChangeStart',(...argus)=>{ console.log('5.hashChangeStart,Hash路由切换之前,参数为:',...argus); }) Router.events.on('hashChangeComplete',(...argus)=>{ console.log('6.hashChangeComplete,Hash路由切换完成,参数为:',...argus); }) function goto(){ Router.push({ pathname:'/chuancan', query:{ name:'张三' } }) }
return ( <> <div>我是首页</div> <div> <Link href="/chuancan?name=张三"> <a>张三</a> </Link> <Link href={{pathname:'/chuancan',query:{name:'李四'}}}> <a>李四</a> </Link> </div> <div> <button onClick={goto}>点击跳转并携带参数</button> </div> </> )
} export default Home
|
Next.js中使用Axios
getiInitialProps是 Next.js 最伟大的发明,它确定了一个规范,一个页面组件只要把访问 API 外部资源的代码放在 getInitialProps 中就足够,其余的不用管,Next.js 自然会在服务器端或者浏览器端调用getInitialProps来获取外部资源,并把外部资源以 props 的方式传递给页面组件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| import React from 'react' import {withRouter} from 'next/router'; import Link from 'next/link' import axios from 'axios';
const Chuancan = ({router,data})=>{ return ( <> <div>{router.query.name}</div> <div> { data.map(ele=>{ return <p key={ele.title}>{ele.title}</p> }) } </div> <Link href='/'><a>返回首页</a></Link> </> ) }
Chuancan.getInitialProps = async ()=>{ const promise = new Promise((resolve)=>{ axios('http://192.168.210.146:9527/api/goodList?page=1').then((res)=>{ console.log('数据:',res); resolve(res) }) }) return await promise } export default withRouter(Chuancan)
|
使用Style jsx编写页面
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| import React,{useState} from 'react';
function Jspang() { const [color,setColor] = useState(); const changeColor=()=>{ setColor(color==='blue'?'red':'blue') }
return ( <> <div>测试文本</div> <div><button onClick={changeColor}>改变颜色</button></div>
<style jsx> {` div{color:${color};} `} </style> </> ) } export default Jspang
|
LazyLoading懒加载
外部库实现方式
采用异步引入的方式,仅在需要的时候引入使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| import React,{useState} from 'react';
function Time() { const [nowTime,setTime] = useState(Date.now())
const changeTime = async ()=>{ const moment = await import('moment') setTime(moment.default(Date.now()).format()) }
return ( <> <div>显示时间:{nowTime}</div> <div><button onClick={changeTime}>改变时间格式</button></div> </> ) }
export default Time
|
自定义库
自定义一个组件
1
| export default ()=><div>Lazy Loading ...</div>
|
引入next的dynamic
仅在使用的时候生效
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| import React,{useState} from 'react'; import dynamic from 'next/dynamic';
const One = dynamic(import('../components/one'));
function Time() { const [nowTime,setTime] = useState(Date.now()) const changeTime = async ()=>{ const moment = await import('moment') setTime(moment.default(Date.now()).format()) } return ( <> <div>显示时间:{nowTime}</div> <One/> <div><button onClick={changeTime}>改变时间格式</button></div> </> ) } export default Time
|
自定义Head
为优化SEO,请求头是必不可少的,自定义请求头可以是SEO更加便捷找到页面
为方便可以将头做成组件,当然也可以每个页面使用不同的Head
使用Next提供的组件<Head/>
1 2 3 4 5 6 7 8 9 10 11
| import Head from 'next/head' const MyHeader = ()=>{ return ( <> <Head> <title>JSPang.com</title> </Head> </> ) } export default MyHeader
|
在需要的时候引入
1 2 3 4 5 6 7 8 9 10 11
| import MyHeader from "../components/myHeader"
export default function Header() { return ( <> <MyHeader/> <div>Header</div> </> ) }
|
Next.js中使用css
Next中是无法正常引入css进行使用的,参考官方文档
- 在pages文件下新建
_app.js
- 新建
style.css
全局样式文件
1 2 3 4 5 6 7
|
import './styles.css';
export default function MyApp({Component,pageProps}){ return <Component {...pageProps}></Component> }
|
- 如果是组件的话可以在组件内引入
1 2 3 4 5 6 7 8 9 10
| import 'antd/dist/antd.css' import {Button} from 'antd'
export default function Header() { return ( <> <Button>按钮</Button> </> ) }
|