title: Next.js
date: 2022-09-08 20:21:53
tags:
- Next.js
categories: - 服务端渲染
Next.js
是什么?
Next.js 是一个轻量级的 React 服务端渲染应用框架。有了它我们可以简单轻松的实现React的服务端渲染,从而加快首屏打开速度,也可以作SEO(收索引擎优化了)。
最初
在没有Next.js的时候,用React开发需要配置很多繁琐的参数,如Webpack配置,Router配置和服务器端配置等…
如果需要作SEO,要考虑的事情就更多了,怎么样服务端渲染和客户端渲染保持一致就是一件非常麻烦的事情,需要引入很多第三方库。但有了Next.js,这些问题都解决了,使开发人员可以将精力放在业务逻辑上!
优点
- 搭建轻松
- 自带数据同步 SSR
- 丰富的插件
- 灵活的配置
搭建
- 手动配置
- 使用
create-next-app
脚手架配置
- 下载所用到的依赖
npm i react react-dom next
- 修改package.json
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev":"next", //项目启动
"build":"next build", //项目打包
"start": "next start" //开启服务
},
1.手动搭建
- 新建文件pages
- 新建index.js
function Index() {
return (
<div>Hello Next.js</div>
)
}
export default Index
- 执行
npm run dev
启动项目调试
无需引入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.导航式跳转
- 新建两个页面
// 这是A页面
import Link from 'next/link'
export default () => (
<>
<div>jspang - A页面</div>
<Link href='/'>
<a>返回首页</a>
</Link>
</>
)
//--------------------------------------------
// 这是B页面
import Link from 'next/link'
export default () => (
<>
<div>jspang - B页面</div>
<Link href='/'>
<a>返回首页</a>
</Link>
</>
)
- 编写首页
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
注意点
- Link标签中只能包含一个跟标签,不能有同级标签
2.编程式跳转
使用Router方法可以实现跳转页面
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进行传递
import React from 'react'
import Link from 'next/link'
// query传递参数 老版本next.js仅仅支持query传参
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';// 需要使用 withRouter 进行加工
import Link from 'next/link'
const Chuancan = ({router})=>{
return (
<>
<div>{router.query.name}</div>
<Link href='/'><a>返回首页</a></Link>
</>
)
}
export default withRouter(Chuancan)
编程式传参
import React from 'react'
import Link from 'next/link'
import Router from 'next/router'
// query传递参数 老版本next.js仅仅支持query传参
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
组件
export default ({children})=> {
return (
<button>
{children}
</button>
)
}
//写一个简单的组件示例
在首页文件中导入
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路由切换完成
import React from 'react'
import Link from 'next/link'
import Router from 'next/router'
const Home = () =>{
// routeChangeStart 路由发生变化之前
// routeChangeComplete 路由发生变化之后
// beforeHistoryChange Next.js全部都用History模式
// routeChangeError 路由发生错误时,404不算
// hashChangeStart Hash路由切换之前
// hashChangeComplete Hash路由切换完成
Router.events.on('routeChangeStart',(...argus)=>{
// ...argus 返回路径和{shallow: false}对象
console.log('1.routeChangeStart,路由开始变化,参数为:',...argus);
})
Router.events.on('routeChangeComplete',(...argus)=>{
// ...argus 返回路径和{shallow: false}对象
console.log('2.routeChangeComplete,路由变化结束,参数为:',...argus);
})
Router.events.on('beforeHistoryChange',(...argus)=>{
// ...argus 返回路径和{shallow: false}对象
console.log('3.beforeHistoryChange,参数为:',...argus);
})
Router.events.on('routeChangeError',(...argus)=>{
// ...argus 返回路径和{shallow: false}对象
console.log('4.routeChangeError,路由发生错误时,参数为:',...argus);
})
Router.events.on('hashChangeStart',(...argus)=>{
// ...argus 返回路径和{shallow: false}对象
console.log('5.hashChangeStart,Hash路由切换之前,参数为:',...argus);
})
Router.events.on('hashChangeComplete',(...argus)=>{
// ...argus 返回路径和{shallow: false}对象
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 的方式传递给页面组件。
import React from 'react'
import {withRouter} from 'next/router';
import Link from 'next/link'
import axios from 'axios';
const Chuancan = ({router,data})=>{ // 仅仅在withRouter下使用
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编写页面
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懒加载
外部库实现方式
采用异步引入的方式,仅在需要的时候引入使用
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
自定义库
自定义一个组件
export default ()=><div>Lazy Loading ...</div>
引入next的dynamic
仅在使用的时候生效
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/>
import Head from 'next/head'
const MyHeader = ()=>{
return (
<>
<Head>
<title>JSPang.com</title>
</Head>
</>
)
}
export default MyHeader
在需要的时候引入
import MyHeader from "../components/myHeader"
export default function Header() {
return (
<>
<MyHeader/>
<div>Header</div>
</>
)
}
Next.js中使用css
Next中是无法正常引入css进行使用的,参考官方文档
- 在pages文件下新建
_app.js
- 新建
style.css
全局样式文件
// _app.js
import './styles.css'; //你的全局css样式
export default function MyApp({Component,pageProps}){
return <Component {...pageProps}></Component>
}
- 如果是组件的话可以在组件内引入
import 'antd/dist/antd.css'
import {Button} from 'antd'
export default function Header() {
return (
<>
<Button>按钮</Button>
</>
)
}