react服务端渲染Next的学习

记录一下Next的学习,
1:手动安装
2:自动安装
好,开始手动安装
//先安装依赖包

npm  init
cnpm  install  react  react-dom  next --save 

//安装完成后,修改package.json,添加如下命令

  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
	"dev":"next",
	"build":"next build",
	"start":"next start"
  },

//测试,新建一个pages文件夹,next会自动给我们设置路由,
//新建一个Index.js,代码如下

//react hooks
function Index(){
	return (
		<div>Hello,next</div>
	)		
}


export default Index;

//启动,测试

npm  run  dev

image.png

image.png
启动成功啦

·······························································································
现在我们用工具脚手架来创建一个项目,工作中都是用这个方式哦
先来全局安装一下

cnpm  install  create-next-app -g

image.png

创建项目
目前可以支持三种方式的创建,分别是用npx,yarn和create-next-app命令来进行安装
npx 是Node自带的npm模块,所以你只要安装了Node都是可以直接使用npx命令的。

但低版本的Node是不带这个命令的,所以你需要手都安装一下。

cnpm install -g npx

好,开始创建项目

npx create-next-app next-react

image.png
启动

npm  run  dev

image.png
看到上图就是成功啦
在pages新建一个index.js页面来测试

function user(){
	return(
		<button>测试按钮</button>
	)
}

export default user;

image.png
浏览器输入http://localhost:3000/user,发现自动给我们添加了路由,好方便亚麻跌
image.png

类似于一个js就是一个路由,那么如果是2级比如http://localhost:3000/concat/phone,怎么实现了?
其实也很简单,新建一个concat文件夹,里面新建phone.js就可以啦
//phone.js

export default ()=>{
	return <div>好好学习React</div>
}

image.png

image.png
那么如何新建一个组件了?

我们再components文件下下面,新建一个test.js,用来写我们的子组件

export  default ({children})=>{
	return <button>我是一个子组件{children}</button>
}

ps:这里传值只能写children,用别的就不行哦

在首页中使用
index.js

import Test from '../components/test'
<Test >我是传递值</Test>

最后效果
image.png

接下来我们实现路由的跳转,具体有2个方式Link和Router.push,好上代码
新建一个home.js
//home.js


import Link from 'next/link';

import PageA from './pageA.js';
import PageB from './pageB.js';

function  home(){
	return(
		<>
			<div>我是Home页面</div>
			<Link  href='/pagea'><a >去A页面</a></Link>
			<Link  href='/pageb'><a>去B页面</a></Link>
		</>
	)
	
}

export default home;

ps:官方推荐link里面用a标签包裹,否则会有警告

//pageA.js

import Link from 'next/link';
export  default ()=>{
	return (
		<>
			<Link href='/home'><a >返回首页</a></Link>
			<div>我是AAA页面</div>
		</>
		)
}

//pageB.js

import Link from 'next/link';
export  default ()=>{
	
	return (
		<>
			<Link href='/home'><a >返回首页</a></Link>
			<div>我是BBB页面</div>
		</>	
	)
}

效果图
image.png

image.png

image.png

好,我们用单击事件来是线路有跳转

import Router  from 'next/router'
function  home(){
	return(
		<>
			<div>我是Home页面</div>
			<Link  href='/pagea'><a >去A页面</a></Link>
			<Link  href='/pageb'><a>去B页面</a></Link>
			<div>
				<button onClick={()=>{Router.push('/pagea')}}>点击去A页面</button>
				<button onClick={()=>{Router.push('/pageb')}}>点击去B页面</button>
			</div>
		</>
	)
	
}

image.png
image.png

image.png
用方法也是可以的哦

<div>
				<button onClick={()=>{Router.push('/pagea')}}>点击去A页面</button>
				<button onClick={()=>{Router.push('/pageb')}}>点击去B页面</button>
				<button onClick={gotoPage}>点击去C页面</button>
			</div>

接下来讲解一下,路由传递参数和接受参数,next只支持query传递参数哦

<Link  href='/pagea?name=深圳'><a >去A页面</a></Link>
<Link  href='/pageb?name=成都'><a>去B页面</a></Link>

这里传递2个参数name值,然后我们再pageA和pageB获取name值

import Link from 'next/link';
import {withRouter} from 'next/router';

 const pageA = ({router})=>{
	return (
		<>
			<Link href='/home'><a >返回首页</a></Link>
			<p>我是参数:{router.query.name}</p>
			<div>我是AAA页面</div>
		</>
		)
}

export  default withRouter(pageA);

###主要是使用了withRouter来接受路由参数哦

import Link from 'next/link';
import {withRouter} from 'next/router';

const pageB= ({router})=>{
	
	return (
		<>
			<Link href='/home'><a >返回首页</a></Link>
			<div>我是接受到的参数:{router.query.name}</div>
			<div>我是BBB页面</div>
		</>	
	)
}
export  default withRouter(pageB)

image.png
image.png
函数传递也是可以的

//home.js
	function  gotoPage(){
		Router.push('/pageC?name=武汉')
	};
//pageC.js
import Link from 'next/link';
import {withRouter} from 'next/router';
const pageC= ({router})=>{
	return (
		<>
			<Link href='/home'><a >返回首页</a></Link>
			<div>接受到的参数{router.query.name}</div>
			<div>我是CCC页面</div>
		</>	
	)
}
export  default withRouter(pageC)

image.png
传递参数用面向对象试一下可以不?

	function  gotoPage(){
		Router.push({
			pathname:'/pageC',
			query:{
				name:"我爱武汉"
			}
		})
	};

效果是一样一样的
image.png

接下来讲解下路由的生命周期钩子事件

//routeChangeStart 路由发送变化之前	
//routeChangeComplete	路由变化结束
//beforeHistoryChange 	 路由history开始变化
//routerChangeError   路由发送错误 
//hashChangeStart     hash路由开始改变之前
//	hashChangeComplete	hash路由开始改变完成	 

具体代码
home.js

	Router.events.on('routeChangeStart',(...args)=>{
		console.log('1-routeChangeStart,路由开始变化了之前',...args)
	});
	Router.events.on('routeChangeComplete',(...args)=>{
		console.log('2-routeChangeComplete,路由开始变化完成结束',...args)
	});
	Router.events.on('beforeHistoryChange',(...args)=>{
		console.log('3-beforeHistoryChange,路由history开始变化',...args)
	});
	Router.events.on('routerChangeError',(...args)=>{
		console.log('4-routerChangeError,路由发送错误',...args)
	});
	//hash模式
	Router.events.on('hashChangeStart',(...args)=>{
		console.log('5-hashChangeStart,hash路由开始改变之前',...args)
	});
	Router.events.on('hashChangeComplete',(...args)=>{
		console.log('6-hashChangeComplete,hash路由开始改变完成',...args)
	});

效果图
image.png
hash模式下

<Link  href='#pageb?name=成都'><a>Hash模式</a></Link>

image.png

接下来讲解远程获取数据,官方规定必须放在getInitialProps里面才可以

>cnpm  install axios --save
pageA.getInitialProps= async ()=>{
	//let api = "http://localhost:3333/api/list";
	let api = "/api/list";
	const  result  =  new  Promise((resolve)=>{
			axios(api).then(res=>{
				console.log(res.data.data);
				resolve(res.data.data)
			}).catch(err=>{
				console.log(err);
			});
	});
	return await result;
}

image.png

接下来讲解一下,如何在next中写css

		<>
			<Link href='/home'><a >返回首页</a></Link>
			<div>接受到的参数{router.query.name}</div>
			<div >我是CCC页面</div>
			<div className="red">我是CCC页面</div>
			<style jsx>
			{`
				div{color:blue}
				.red{color:red}
			`}	
			</style>
		</>	

image.png

那么如何动态切换样式了,点一下变红点一下变蓝色

import  {useState} from 'react';
import Link from 'next/link';
import {withRouter} from 'next/router';
const pageC= ({router})=>{
	const [color,setColor]=useState('blue');
	const changeColor = ()=>{
		setColor(color=="blue"?"red":"blue")
	}
	return (
		<>
			<Link href='/home'><a >返回首页</a></Link>
			<div>接受到的参数{router.query.name}</div>
			<div >我是CCC页面</div>
			<div className="red">我是CCC页面</div>
			<button onClick={changeColor}>改变颜色</button>
			<style jsx>
			{`
				div{color:${color}}
				.red{color:red}
			`}	
			</style>
		</>	
	)
}
export  default withRouter(pageC)

大功告成,接下来实现模块懒加载,优化打开速度

>cnpm  install moment --save
import  {useState} from 'react'
import {moment} from 'moment';

const  time= ()=>{
	const [nowTime,setTime]=useState(Date.now());
	const changeTime= ()=>{
		setTime(moment(Date.now()).format())
	}
	return(
		<>
		<div>{nowTime}</div>
		<button onClick={changeTime}>改变时间格式</button>
		</>
	)
}
export default  time;

使用懒加载之后

import  {useState} from 'react'

const  time= ()=>{
	const [nowTime,setTime]=useState(Date.now());
	const changeTime = async ()=>{
		let  moment =await import('moment');
		setTime( moment.default(Date.now()).format())
	}
	return(
		<>
		<div>{nowTime}</div>
		<button onClick={changeTime}>改变时间格式</button>
		</>
	)
}
export default  time;

ps:注意一定要加.default,否则报错,如何判断依据懒加载成功了?
image.png

会发现从0.js又生成1.js,说明成功了~~~~~~

那么如何懒加载自定义组件了????

1:先再components里面新建one.js

export default ()=>{
	return <h3>我是自定义组件哦</h3>
}

2:使用

import dynamic from 'next/dynamic'
import One  from '../components/one';
<One />

写完代码后,可以看到自定义组件是懒加载的,只有在jsx里用到时,才会被加载进来,如果不使用就不会被加载。

当我们作的应用存在首页打开过慢和某个页面加载过慢时,就可以采用Lazy Loading的形式,用懒加载解决这些问题。

接下来讲解如何利用head实现网页的标题title

import Head  from 'next/head'
<Head>
	<title>我要成为React大神</title>
	<meta charset='utf-8' /> 
</Head>

image.png
那么如何全局引用了?
思路:万物皆组件,封装为一个组件,其他页面引用就可以啦
新建一个globalHeader.js作为全局组件
//globalHeader.js

import Head  from  'next/head'

export default ()=>{
	return(
		<>
			<Head>
				<title>我是全局标题</title>
			</Head>
		</>
	)
	
}

其他页面使用

import  GlobalHeader  from '../components/globalHeader';
<GlobalHeader />

效果图
image.png
######我们知道next不能直接导入css使用,这就很尴尬了,那么如何解决了?

image.png
这里用了一个三方库@zeit/next-css来解决

cnpm install --save @zeit/next-css

根目录下新建一个next.config.js

const withCss = require('@zeit/next-css')

if(typeof require !== 'undefined'){
    require.extensions['.css']=file=>{}
}

module.exports = withCss({})

修改配置文件后,一定要重启服务
image.png

大功告成,yeah~~~~~
接下来我们安装antd,这样界面就可以好看很多
1:安装antd

cnpm install antd --save

//注意:antd 默认支持基于 ES module 的 tree shaking,不使用以下插件也会有按需加载的效果。
##按需加载
A使用 babel-plugin-import(推荐)。
B手动引入
这里我们用按需加载
2:配置按需加载
先安装按需加载的模块

>cnpm  install babel-plugin-import --save

根目录下面新建.babelrc 文件

{
  "presets":["next/babel"],	//Next.js的总配置文件,相当于继承了它本身的所有配置	
  "plugins": [//增加新的插件,这个插件就是让antd可以按需引入,包括CSS
    ["import", {
      "libraryName": "antd",
      "style": "css" // `style: true` 会加载 less 文件
    }]
  ]
}

ps:presets是保留以前的配置,注意官网的libraryDirectory这个千万不要加,有个坑,加了编译报错无法访问
使用

import {Button} from 'antd';
<Button>我是antd按钮</Button>

image.png

最后打包上线

npm  run  build

但是当你使用了Ant Desgin后,在打包的时候会遇到一些坑。我们引入了就会有如下问题
报错如下
image.png
那么如何解决了?

1:修改.babelrc文件,去掉"style": "css"这一行

{
  "presets":["next/babel"],	
  "plugins": [
    ["import", {
      "libraryName": "antd"
    }]
  ]
}

2:在pages文件下下面新建一个_app.js,内容如下

import App  from  'next/app';

import 'antd/dist/antd.css';

export default App;

3:重新打包测试

npm run  build  

看到如下界面就成功啦
image.png
4:启动测试

  "scripts": {
    "dev": "node server.js",
    "build": "next build",
    "start": "next start -p 80"
  },

启动

npm  run  start

image.png

没有问题,大功告成~~~~~~~~~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值