赞
踩
本教程用的Next.js 是 13 版本
npm init
npm install --save react react-don next
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "next",
"build": "next build",
"start": "next start"
},
在根目录下创建pages文件夹,并在该文件下创建 index.js
pages 文件夹是Next 规定的,在这个文件夹下写入的文件,Next.js 会自动创建对应的路由
function Index() {
return (
<div>Halo Next.js</div>
)
}
export default Index
运行 npm run dev
npx create-next-app@latest
第一次创建项目,若没有安装nextjs 会提示是否安装
What is your project named? my-app // 项目名
Would you like to use TypeScript? No / Yes // TypeScript
Would you like to use ESLint? No / Yes // ESLint
Would you like to use Tailwind CSS? No / Yes // Tailwind CSS
Would you like to use `src/` directory? No / Yes // src 作为根目录
Would you like to use App Router? (recommended) No / Yes // 路由
Would you like to customize the default import alias? No / Yes // 自定义默认导入别名
What import alias would you like configured? @/* // 配置什么导入别名
运行 npm run dev
在page目录下创建 about.js
function About () {
return (
<div>About nextjs</div>
)
}
export default About
访问 http://localhost:3000/about
在 Next.js 中,一个 page(页面) 就是一个从 .js
、jsx
、.ts
或 .tsx
文件导出(export)的 React 组件 ,这些文件存放在 pages
目录下。每个 page(页面)都使用其文件名作为路由(route)
在page目录下创建 home 文件 并在该文件下创建 home.js
function Home () {
return (
<div>home nextjs</div>
)
}
export default Home
访问 http://localhost:3000/home/home
在src目录下创建 components 目录,并在该目录下创建 buttonComponent.js 文件
export default ({children})=><button>{children}</button>
在home.js 引入
import dynamic from 'next/dynamic'
const ButtonComponent = dynamic(
() => import('@/components/buttonComponent'),
// { ssr: false } // 是否关闭 ssr(服务端渲染) 默认是开启
)
<ButtonComponent>按钮</ButtonComponent>
在home页面新增两个页面
homeA.js
import React from "react";
import Link from "next/link";
const HomeA = () => {
return (
<>
<div>我是HomeA 页面</div>
<div><Link href="/home/home"><div>去Home页面</div></Link></div>
</>
)
}
export default HomeA
homeB.js
import React from "react";
import Link from "next/link";
const HomeB = () => {
return (
<>
<div>我是HomeB 页面</div>
<div><Link href="/home/home"><div>去Home页面</div></Link></div>
</>
)
}
export default HomeB
修改home页面内容
import React from "react"
import Link from "next/link"
function Home () {
return (
<div>
<div>home nextjs</div>
<div><Link href="/home/homeA"><div>去homeA页面</div></Link></div>
<div><Link href="/home/homeB"><div>去homeB页面</div></Link></div>
</div>
)
}
export default Home
早期版本 Link标签下是要接上a标签的,当前版本(13.4.19)如果加上a标签会报错
修改home.js页面
import React from "react" import Router from "next/router" const goHomeA = () => { Router.push('/home/homeA') } const goHomeB = () => { Router.push('/home/homeB') } function Home () { return ( <div> <div>home nextjs</div> <div onClick={goHomeA}>去homeA页面</div> <div onClick={goHomeB}>去homeB页面</div> </div> ) } export default Home
Next.js 只能通过 query 来传递参数
修改home.js页面
import React from "react"
import Link from "next/link"
function Home () {
return (
<div>
<div>home nextjs</div>
<div><Link href="/home/homeA?name=张三&age=18"><div>张三</div></Link></div>
<div><Link href="/home/homeA?name=李四&age=20"><div>李四</div></Link></div>
</div>
)
}
export default Home
修改homeA.js页面
withRouter 是 Next.js 框架的高级组件,用来处理路由用的
import React from "react"; import Link from "next/link"; import { withRouter } from "next/router"; function Home () { return ( <div> <div>home nextjs</div> <div><Link href="/home/homeA?name=张三&age=18"><div>写法一</div></Link></div> <div><Link href={{ pathname: '/home/homeA', query: { name: '李四', age: 20 } }}><div>写法二</div></Link></div> </div> ) } export default withRouter(HomeA)
import React from "react" import Router from "next/router" const goHomeA = () => { Router.push('/home/homeA?name=张三&age=18') } const goHomeA2 = () => { Router.push({ pathname: '/home/homeA', query: { name: '李四', age: 20 } }) } function Home () { return ( <div> <div>home nextjs</div> <div onClick={goHomeA}>写法一</div> <div onClick={goHomeA2}>写法二</div> </div> ) } export default Home
import React from "react" import Router from "next/router" Router.events.on('routeChangeStart', (...args) => { console.log('routeChangeStart -> 路由开始变化', ...args) }) Router.events.on('routeChangeComplete', (...args) => { console.log('routeChangeComplete -> 路由结束变化', ...args) }) Router.events.on("beforeHistoryChange", (...args) => { console.log('beforeHistoryChange -> 在改变浏览器 history 之前触发', ...args) }) Router.events.on('routeChangeError', (...args) => { console.log('routeChangeError -> 跳转发生错误', ...args) }) const goHomeA = () => { Router.push('/home/homeA?name=张三&age=18') } const goHomeA2 = () => { Router.push({ pathname: '/home/homeA', query: { name: '李四', age: 20 } }) } function Home () { return ( <div> <div>home nextjs</div> <div onClick={goHomeA}>写法一</div> <div onClick={goHomeA2}>写法二</div> </div> ) } export default Home
Router.events.on('hashChangeStart', (...args) => {
console.log('hashChangeStart -> 路由开始变化', ...args)
})
Router.events.on('hashChangeComplete', (...args) => {
console.log('hashChangeComplete -> 路由结束变化', ...args)
})
getInitialProps
是挂在 React
组件上的静态方法
如果你使用的是 Next.js 9.3 或更高版本,我们建议你使用 getStaticProps
或 getServerSideProps
来替代 getInitialProps
。
官方推荐的是fetch
在page目录新建一个request.js 页面
import { withRouter } from "next/router"; function Request ({router, data}) { return ( <> <div>{router.name}</div> <div>请求页面 {data} </div> </> ) } Request.getInitialProps = async () => { const res = await fetch('https://api.github.com/repos/vercel/next.js') const json = await res.json() console.log(json) return { stars: json.stargazers_count } } export default withRouter(Request)
index.js
import Router from "next/router" const goRequest = () => { Router.push({ pathname: '/request', query: { name: '李四', age: 20 } }) } export default function Home() { return ( <> <div>首页</div> <div onClick={goRequest}>去Request页面</div> </> ) }
运行页面,可以发现,getInitialProps
会在服务端渲染时执行,也会在客户端渲染时执行
Nextjs
使用服务端渲染的方式返回页面数据此时 getInitialProps
会在服务端执行,浏览器端不会执行
Nextjs
服务端渲染所以实际上 getInitialProps
方法会根据当前页面渲染时的端侧不同,自主地选择在 Node 端还是 Client 端执行
getStaticProps
会在每次页面访问时被请求
修改request.js
import { withRouter } from "next/router"; function Request ({router, content}) { return ( <> <div>{router.name}</div> <div>请求页面 {content} </div> </> ) } export const getStaticProps = async () => { const res = await fetch('https://api.github.com/repos/vercel/next.js') const json = await res.json() console.log(json) return { props: { content: json.stargazers_count } }; }; export default withRouter(Request)
getStaticProps是用于在构建时预先执行getInitialProps进行的处理并预先生成静态文件的API。 不会在客户端上运行。 始终在服务器端运行。
import { withRouter } from "next/router"; function Request ({router, content}) { return ( <> <div>{router.name}</div> <div>请求页面 {content} </div> </> ) } export const getServerSideProps = async context => { const res = await fetch('https://api.github.com/repos/vercel/next.js') // if (!res) { // notFound 强制页面跳转到 404 // return { // notFound: true // }; // redirect 来将页面重定向 // return { // redirect: { // destination: '/', // permanent: false // } // }; // } const json = await res.json() console.log(json) return { props: { content: json.stargazers_count } }; } export default withRouter(Request)
通过 next.js
的 getServerSideProps
,我们在开发中可以很好的协调前后端数据,一些页面初始化数据、页面鉴权可以直接在 getServerSideProps
中进行处理,这样可以大大简化页面逻辑,还保障前后端的统一性。
新建style.js 页面
const Style = () => { return ( <> <div>style 页面</div> <div className="base">基础</div> <style jsx> {` .base { color: blue; font-size: 16px; margin: 40px; display: block; } `} </style> </> ) } export default Style
要注意,style 后面要jsx next.js 会自动加入一个随机类名,这样就防止CSS的全局污染,如上述代码 base 会变成 base-xxxxxx
修改style.js 页面
import React, {useState} from "react" const Style = () => { const [color, setColor] = useState('blue') const [fontSize, setFontSize] = useState('16') const [margin, setMargin] = useState('40') const changeColor = () => { setColor(color === 'blue' ? 'red': 'blue') } const changeFontSize = () => { setFontSize(fontSize === '16' ? '20': '16') } const changeMargin = () => { setMargin(margin === '10' ? '40': '10') } return ( <> <div>style 页面</div> <div className="base">基础</div> <button onClick={changeColor}>改颜色</button> <button onClick={changeFontSize}>改字体大小</button> <button onClick={changeMargin}>改边距</button> <style jsx> {` .base { color: ${color}; font-size: ${fontSize}px; margin: ${margin}px; display: block; } `} </style> </> ) } export default Style
新建 import.js 页面
引入 dayjs 库
npm i dayjs
如果我们在页面直接引入,那它就会以公共库的形式进行打包发布,就算项目第一个页面不使用moment
也会进行加载,这就是资源浪费
import.js
import React,{useState} from "react"; const Import = () => { const [time, setTime] = useState() const changeTime = async () => { const dayjs = await import('dayjs') setTime(dayjs.default(Date.now()).format('YYYY-MM-DD HH:mm:ss')) } return ( <> <div>import 页面</div> <div>当前时间为:{time}</div> <button onClick={changeTime}>获取当前时间</button> </> ) } export default Import
可以看到我们是在需要的地方才引入
要注意 使用 default 才能生效
利用 dynamic 引入组件实现
import dynamic from 'next/dynamic'
const ButtonComponent = dynamic(() => import('@/components/buttonComponent'))
const Import = () => {
return (
<>
<div>import 页面</div>
<ButtonComponent>按钮</ButtonComponent>
</>
)
}
export default Import
自定义组件是懒加载的,只有在jsx
里用到<ButtonComponent/>
时,才会被加载进来,如果不使用就不会被加载
那为了更好的进行SEO优化,可以自己定制<Head>
标签
创建header.js页面
Next.js
已经把<Head>
封装好了,本身就是一个组件,可以直接
import Head from 'next/head'
const Header = ()=>{
return (
<>
<Head>
<title> 头部 </title>
</Head>
</>
)
}
export default Header
Ant Design是一款阿里开源的前端组件库
从React的角度来讲,它就是一个组件库,里边封装了开发中最常用的一些组件,让我们可以通过简单的配置就可以使用他们
首先创建一个 pages/_app.js(如果不存在的话)。 然后import 该 styles.css
文件。
样式表的全局特性
旧版本可以通过 @zeit/next-sass 支持css,这个在新版本中已移除
[name].module.css
文件命名约定来支持 CSS 模块CSS 模块通过自动创建唯一的类名从而将 CSS 限定在局部范围内。 这使您可以在不同文件中使用相同的 CSS 类名,而不必担心冲突。
此行为使 CSS 模块成为包含组件级 CSS 的理想方法。 CSS 模块文件 可以导入(import)到应用程序中的任何位置
不加module next.js框架会误以为是全局样式,会引发冲突报错
import styles from '@/styles/test.module.css'
const Ant = () => {
return (
<>
<div>Ant 页面</div>
<p className={styles.default}>测试</p>
</>
)
}
export default Ant
安装scss
npm install sass
用法与 css一致
import styles from '@/styles/test.module.scss'
const Ant = () => {
return (
<>
<div>Ant 页面</div>
<p className={styles.default}>测试</p>
</>
)
}
export default Ant
npm install antd --save
新建react.js 页面
import React from 'react';
import { DatePicker } from 'antd';
const App = () => {
return <DatePicker />;
};
export default App;
为了不让webpack
把整个Ant Design
的包都进行打包到生产环境
我们需要你用到 babel
npm install --save babel-plugin-import
在项目根目录建立.babelrc
文件
{
"presets":["next/babel"], //Next.js的总配置文件,相当于继承了它本身的所有配置
"plugins":[ //增加新的插件,这个插件就是让antd可以按需引入,包括CSS
[
"import",
{
"libraryName":"antd"
}
]
]
}
这样我们使用那个组件就打包那个组件,同样CSS也是按需打包的
配置package.json 文件夹
"start": "next start -p 8088"
运行打包
npm run build
运行打包好的文件
npm run start
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。