Next.js作为当前非常火热的React的服务端渲染框架,到底有什么强大的地方呢,我们又如何使用hooks的特性去编写 Next.js 的业务逻辑呢,别着急,慢慢向下看。
注意,关于服务端渲染(SSR)的内容我在之前的Nuxt.js中有详细的讲述过,感兴趣的小伙伴可以去这个链接查看。
目录
项目结构
开个小 demo:
.next我们先不需要管,我目前的理解就是存放配置文件的,component就是组件,并不是只React中一切皆组件的哪个组件,而是与pages文件夹不同意义的组件。在Pages文件夹中我们可以看到这里是定义我们视图层的地方,类似于Vue中的view文件夹的作用。
最简单的路由跳转在Next中是不需要我们配置的,采用文件结构即可完成路由结构,Nest中同样有这种东西,如果学过Nest的话对这种比较方便的配置应该很熟悉。如上图的三个pages文件分别代表about,/,post三个路由界面,如果想继续探求深层次路由直接添加文件夹即可。
路由
路由前面我们也稍微提到过一些了,这里尝试去探求更多的功能,首先是关于路由转换,在Next中有两种实现的方式,分别是标签转换和逻辑转换的实现方式:
<Link href="/"><a>To</a></Link>
<button onClick={()=>{Router.push('/')}}>To</button>
两种方式都可以完成我们想要的路由转换功能,当然要引用一些东西:
import Link from 'next/link'
import Router from 'next/router'
接着是动态路由,我们这里就看一个小demo:
// index.js
import Link from 'next/link'
const Home = () => {
return (
<div>
<h2>Home</h2>
<Link href='/about'><a>To About</a></Link>
<Link href='/post?name=第一天'>To Posts</Link>
</div>
)
}
export default Home
// about.js
import Link from 'next/link'
import Router from 'next/router'
const About = () => {
return (
<div>
<h3>About</h3>
<Link href='./'><a>Back Home</a></Link>
<button onClick={()=>{Router.push('/post?name=第二天')}}>To Post</button>
</div>
)
}
export default About
// post.js
import {withRouter} from 'next/router'
import Router from 'next/router'
const Post = ({router}) => {
return (
<div>
<div>{router.query.name}过的不错</div>
<button onClick={()=>{Router.push('/')}}>Home</button>
</div>
)
}
export default withRouter(Post)
这里使用了两种方法向post.js传递动态路由,当我们从index.js点击To Post的链接还有从about.js点击 To Post时,我们可以看到不同的效果,前者显示的是第一天,而后者显示的是第二天。
没错实现动态路由依然有两种方式,看你的业务逻辑而实现。
钩子函数
关于路由的钩子函数,在我们实际业务中应该会比较广泛的使用的到,这里先罗列出来,基本都是成对的:
- routerChangeStart,顾名思义,在路由变化开始时执行,routerChangeComplete即路由变化结束时执行的事件。
- beforeHistoryChange,history即http中和harsh相对的那个history,注意在Next中所有的单页应用路由转换都采用的history模式。执行的时候会在上例1的开始和结束中间执行。
- routerChangeError,注意404并不算这个函数的事件。
- harshChangeStart和harshChangeComplete,即harsh模式的方法。
Axios
下面是获取服务器的API,注意在Next.js中,我们只能写在.getInitialProps中,下面是我用本地的Nest.js写的API获取到的方法,写法很多种。
Post.getInitialProps = async () => {
const res = await axios.get('http://localhost:4000/posts')
console.log(res.data)
return {data: res.data}
}
jspang大佬采用的是这样的写法:
Xiaojiejie.getInitialProps = async ()=>{
const promise =new Promise((resolve)=>{
axios('https://www.easy-mock.com/mock/5cfcce489dc7c36bd6da2c99/xiaojiejie/getList').then(
(res)=>{
console.log('远程数据结果:',res)
resolve(res.data.data)
}
)
})
return await promise
}
相信熟悉JS的应该都能看懂,我就不解释了。
关于CSS
在Next.js中,我们可以使用<style jsx>{``}</style>来获取样式:
import Head from 'next/head'
import {useState} from 'react'
const Color = () => {
const [color, setColor] = useState('blue')
const changeColor = () => {
setColor(color=='blue'?'red':'blue')
}
return (
<>
<Head><title>颜色</title></Head>
<div>显示颜色变化 {color} </div>
<button onClick={changeColor}>改变颜色</button>
<style jsx>
{`
div{
color: ${color};
}
`}
</style>
</>
)
}
export default Color
上面是一段获取样式的代码,包括何如动态的改变样式,我们使用到了$符号。
关于模块懒加载,分为外部模块的懒加载和内部组件的懒加载,这里有兴趣的小伙伴直接去看这个网站即可。
更好的SEO
我们用服务端渲染一个很重要的原因就是SEO的问题,而title作为SEO非常重要的一部分是我们不能忽略的,Next.js对每个页面的自定义title提供了方便的用法。
关于这个的例子我们看上一章的代码即可,我们引入了Head,并且直接写个Head标签即可,当然不只是title,像meta等便签我们也可以使用。
Antd
首先我们上上章已经讲过了,Next.js是不支持我们使用引入CSS的这种操作的,因此我们使用antdesign也就无从谈起了。
真的嘛?当然不是,官方推出了一系列插件来弥补这个问题,包括@zeit/next-css和@zeit/next-sass等,目的就是让我们可以直接引用CSS或者SCSS等文件。
标准配置两部曲如下:
-
yarn add @zeit/next-css
先安装呗
-
根目录下创建next.config.js,添加如下配置文件:
const withCss = require('@zeit/next-css') if(typeof require !== 'undefined'){ require.extensions['.css']=file=>{} } module.exports = withCss({})
注意直接复制即可,没必要改动。
搞定之后就可以引入CSS文件了。
到这里,还有个问题就是因为antd这种UI库都是大而全的,我们直接引用的话肯定会很影响性能,我们可以使用一个插件来实现按需引入的方法:
-
yarn add babel-plugin-import
先安装
-
{ "presets": ["next/babel"], "plugins": [ [ "import", { "libraryName":"antd", "style":"css" } ] ] }
根目录创建.babelrc文件,复制即可。
这样就可以使用我们的antd中的内容了:
import Link from 'next/link'
import {Button} from 'antd'
const Home = () => {
return (
<div>
<h2>Home</h2>
<Button>dangdangdang</Button>
...