记录一下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
启动成功啦
·······························································································
现在我们用工具脚手架来创建一个项目,工作中都是用这个方式哦
先来全局安装一下
cnpm install create-next-app -g
创建项目
目前可以支持三种方式的创建,分别是用npx,yarn和create-next-app命令来进行安装
npx 是Node自带的npm模块,所以你只要安装了Node都是可以直接使用npx命令的。
但低版本的Node是不带这个命令的,所以你需要手都安装一下。
cnpm install -g npx
好,开始创建项目
npx create-next-app next-react
启动
npm run dev
看到上图就是成功啦
在pages新建一个index.js页面来测试
function user(){
return(
<button>测试按钮</button>
)
}
export default user;
浏览器输入http://localhost:3000/user,发现自动给我们添加了路由,好方便亚麻跌
类似于一个js就是一个路由,那么如果是2级比如http://localhost:3000/concat/phone,怎么实现了?
其实也很简单,新建一个concat文件夹,里面新建phone.js就可以啦
//phone.js
export default ()=>{
return <div>好好学习React</div>
}
那么如何新建一个组件了?
我们再components文件下下面,新建一个test.js,用来写我们的子组件
export default ({children})=>{
return <button>我是一个子组件{children}</button>
}
ps:这里传值只能写children,用别的就不行哦
在首页中使用
index.js
import Test from '../components/test'
<Test >我是传递值</Test>
最后效果
接下来我们实现路由的跳转,具体有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>
</>
)
}
效果图
好,我们用单击事件来是线路有跳转
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>
</>
)
}
用方法也是可以的哦
<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)
函数传递也是可以的
//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)
传递参数用面向对象试一下可以不?
function gotoPage(){
Router.push({
pathname:'/pageC',
query:{
name:"我爱武汉"
}
})
};
效果是一样一样的
接下来讲解下路由的生命周期钩子事件
//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)
});
效果图
hash模式下
<Link href='#pageb?name=成都'><a>Hash模式</a></Link>
接下来讲解远程获取数据,官方规定必须放在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;
}
接下来讲解一下,如何在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>
</>
那么如何动态切换样式了,点一下变红点一下变蓝色
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,否则报错,如何判断依据懒加载成功了?
会发现从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里用到<One/>时,才会被加载进来,如果不使用就不会被加载。
当我们作的应用存在首页打开过慢和某个页面加载过慢时,就可以采用Lazy Loading的形式,用懒加载解决这些问题。
接下来讲解如何利用head实现网页的标题title
import Head from 'next/head'
<Head>
<title>我要成为React大神</title>
<meta charset='utf-8' />
</Head>
那么如何全局引用了?
思路:万物皆组件,封装为一个组件,其他页面引用就可以啦
新建一个globalHeader.js作为全局组件
//globalHeader.js
import Head from 'next/head'
export default ()=>{
return(
<>
<Head>
<title>我是全局标题</title>
</Head>
</>
)
}
其他页面使用
import GlobalHeader from '../components/globalHeader';
<GlobalHeader />
效果图
我们知道next不能直接导入css使用,这就很尴尬了,那么如何解决了?
这里用了一个三方库@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({})
修改配置文件后,一定要重启服务
大功告成,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>
最后打包上线
npm run build
但是当你使用了Ant Desgin后,在打包的时候会遇到一些坑。我们引入了就会有如下问题
报错如下
那么如何解决了?
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
看到如下界面就成功啦
4:启动测试
"scripts": {
"dev": "node server.js",
"build": "next build",
"start": "next start -p 80"
},
启动
npm run start
没有问题,大功告成~~~~~~~~~