next.js开发基础

407 阅读4分钟

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')
	})
})