react next
1.热代码更新,自动路由,单文件组件,服务端渲染
2.生态系统兼容:next.js与js,node,react生态系统协助良好
3.自动分割代码,预读取,动态组件,静态输出
安装
1.npm install --save next react react-dom
{
"name": "y",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"dev": "next",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"next": "^9.0.2",
"react": "^16.8.6",
"react-dom": "^16.8.6"
}
}
2.页面文件写在pages文件中
样式使用
支持css/sass/less/stylus files 可以使用如下组件
@zeit/next-css
@zeit/next-sass
@zeit/next-less
@zeit/next-stylus
npm install @zeit/next-css -S
npm install @zeit/next-sass node-sass -S
主要sass语法
h1
color: red
配置next.config.js文件
//单一写法
// const withCSS = require('@zeit/next-css')
// module.exports = withCSS()
// 结合css和sass
const withCSS = require('@zeit/next-css')
const withSass = require('@zeit/next-sass')
module.exports = {
webpack(config, ...args){
config = withCSS().webpack(config, ...args);
config = withSass().webpack(config, ...args);
return config;
}
}
配置.babelrc文件
{
"presets": [
"next/babel"
],
"plugins": [
[
"import",
{
"libraryName": "antd",
"libraryDirectory":"lib",
"style": true
}
]
]
}
css内联方式
==标题符号 反单引号 不是双引号==
<div>
<h1>hellow 内联!! </h1>
<style jsx>{`
h1 {
color:orange;
}
`}</style>
</div>
定制header
第一种方式
import Header from 'next/head'
import '../styles/index.sass'
// 无状态组件
export default () => (
<div>
<Header>
<title>next教程</title>
<meta charSet='utf-8' />
</Header>
<h1>hellow word somple !! </h1>
</div>
)
第二种方法 定制全局layout并复用
import Head from 'next/head'
export default ({children}) => (
<div>
<Head>
<title>公共头部测试-next教程</title>
</Head>
{children}
<footer>
版权所有,未经允许,也可以分享。
</footer>
</div>
)
import Layout from './components/layout'
import '../styles/index.sass'
// 无状态组件
export default () => (
<div>
<Layout>
<h1>hellow word somple !! </h1>
</Layout>
</div>
)
数据获取和生命周期
1.getInitialProps在初始化组件props属性时被调用,只在服务器端运行,没有跨域的限制
2.不能用于子组件上,只能用于页面组件上
import React from 'react'
import axios from 'axios'
export default class Films extends React.Component{
static async getInitialProps(){
const res = await axios.get('http://m.maizuo.com/gateway?cityId=330100&pageNum=1&pageSize=10&type=1&k=2341043',{
headers:{
'X-Host': 'mall.film-ticket.film.list' //设置防盗链
}
})
console.log(res)
return {
films: res.data.data.films
}
}
render(){
return (
<div>
<h2>电影</h2>
<ul>
{
this.props.films.map(item => {
return <li key={item.filmId}>
{item.name}
<img src={item.poster} />
</li>
})
}
</ul>
</div>
)
}
}
路由配置
- 基本路由功能:next默认是按照文件结构进行页面跳转
link跳转
编程式跳转
参数传递
- 路由遮盖
<Link as="m" href="/list">列表页</Link>
方便简写路由 给长路径起别名
link跳转
import Head from 'next/head'
import Link from 'next/link'
export default ({children}) => (
<div>
<Head>
<title>公共头部测试-next教程</title>
</Head>
<div>
<Link href="/">主页</Link>|
<Link as="m" href="/list">列表页</Link>|
<Link href="/nestStyle">内联样式</Link>|
</div>
{children}
<footer>
版权所有,未经允许,也可以分享。
</footer>
</div>
)
传参跳转
import React from 'react'
import '../styles/list.css'
import Layout from './components/layout'
import Router from 'next/router'
class List extends React.Component{
state = {
list:["hellow","nice-to-meet-you","I-am-Ok"]
}
render(){
return (
<Layout>
<div>
<ul className="uls">
{this.state.list.map((item,index)=>{
return <li key={index} onClick={() => Router.push({
pathname: "/detail",
query: {
arg: item
}
})}>{item}</li>
})}
</ul>
</div>
</Layout>
)
}
}
export default List
// 第一种方法
// return <li key={index} onClick={() => Router.push('/detail?arg=' + item )}>{item}</li>
// 第二种方法
//{this.state.list.map((item,index)=>{
// return <li key={index} onClick={() => Router.push({
// pathname: "/detail",
// query: {
// arg: item
// }
// })}>{item}</li>
// })}
路由的预加载
线上有效果
1.<link>标签添加prefetch属性
import Head from 'next/head'
import Link from 'next/link'
import withRouer from 'next/router'
export default ({children}) => (
<div>
<Head>
<title>公共头部测试-next教程</title>
</Head>
<div>
<Link href="/" prefetch>主页</Link>|
<Link href="/list" prefetch>列表页</Link>|
<Link href="/nestStyle" prefetch>内联样式</Link>|
<Link href="/films" prefetch>电影详情</Link>|
</div>
{children}
<footer>
版权所有,未经允许,也可以分享。
</footer>
</div>
)
2.使用withRouter高阶组件,在组件中使用router.prefetch('/dynamic')
路由的事件和路由守卫
- routeChangeStart(url) 路由跳转开始
- routeChangeComplete(url) 路由跳转完成
- routeChangeError(err,url) 路由跳转失败
- beforeHistoryChange(url) 浏览器历史改变
自定义错误页面
在pages目录里创建_error.js,定制自己的错误页面
redux使用
使用脚手架创建工程
npm install -g create-next-app
create-next-app --example with-redux with-redux-app
程序文件解读
- _app.js覆盖next的app配置,全局引入redux
- with_redux-store.js 高阶组件, 用来向——app.js注入store
- store.js 初始化store和编写reducer
使用next部署
- 打包:next build
- 运行: next start -p 80
package.json
{
"name": "with-redux",
"version": "1.0.0",
"scripts": {
"dev": "next",
"build": "next build",
"start": "next start -p 80",
"dev_e": "cross-env NODE_EMV=dev node server.js",
"start_e": "cross-env NODE_EMV=production node server.js"
},
"dependencies": {
"cross-env": "^5.2.0",
"express": "^4.17.1",
"next": "latest",
"react": "^16.7.0",
"react-dom": "^16.7.0",
"react-redux": "^5.0.1",
"redux": "^3.6.0",
"redux-devtools-extension": "^2.13.2"
},
"license": "ISC"
}
server.js
const express = require('express')
const next = require('next')
const dev = process.env.NODE_EMV !== 'production'
const app = next({dev})
const handle = app.getRequestHandler()
app.prepare().then(() => {
const server = express()
server.get('*', (req,res) => {
return handle(req,res)
})
server.listen(3000, (err) => {
console.log('Ready on http://localhost:3000')
})
})