Next.js

Next.js 是一个轻量级的React服务端渲染框架,简化了React应用的配置,支持SEO。本文介绍了Next.js的搭建、路由管理、组件使用、数据获取以及性能优化策略,包括懒加载、自定义Head和使用Axios。通过实例展示了编程式和路由式跳转、传参以及监听路由变化的方法。
摘要由CSDN通过智能技术生成

title: Next.js
date: 2022-09-08 20:21:53
tags:

  • Next.js
    categories:
  • 服务端渲染

Next.js

是什么?

Next.js 是一个轻量级的 React 服务端渲染应用框架。有了它我们可以简单轻松的实现React的服务端渲染,从而加快首屏打开速度,也可以作SEO(收索引擎优化了)。

Next.js官方文档

最初

在没有Next.js的时候,用React开发需要配置很多繁琐的参数,如Webpack配置,Router配置和服务器端配置等…

如果需要作SEO,要考虑的事情就更多了,怎么样服务端渲染和客户端渲染保持一致就是一件非常麻烦的事情,需要引入很多第三方库。但有了Next.js,这些问题都解决了,使开发人员可以将精力放在业务逻辑上!

优点

  1. 搭建轻松
  2. 自带数据同步 SSR
  3. 丰富的插件
  4. 灵活的配置

搭建

  1. 手动配置
  2. 使用create-next-app脚手架配置
  1. 下载所用到的依赖npm i react react-dom next
  2. 修改package.json
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev":"next",            //项目启动
    "build":"next build",    //项目打包
    "start": "next start"    //开启服务
  },

1.手动搭建

  • 新建文件pages
  • 新建index.js
function Index() {
    return (
        <div>Hello Next.js</div>
    )
}
export default Index
  • 执行npm run dev启动项目调试

无需引入React就可以使用

2.脚手架

  1. 全局安装 npm i -g create-next-app
  2. 创建基础项目npx create-next-app 项目名字
    • npx create-next-app next-create

image-20220908210825826

项目大致结构如上,正常都知道是干什么的。

注:.eslintrc.json文件是规范书写格式的一个第三方包

Next中的路由

在Next中pages文件夹就相当于路由集合,比如说,首页是index.js,而如果url地址变成:3000/jspang.js那么其就会进入jspang.js文件。如果是多层的,那么路径就会变成:3000/blog/nextBlog.js

image-20220908211051641

1.导航式跳转

  1. 新建两个页面
// 这是A页面
import Link from 'next/link'
export default () => (
    <>
        <div>jspang - A页面</div>
        <Link href='/'>
            <a>返回首页</a>
        </Link>
    </>
)

//--------------------------------------------

// 这是B页面
import Link from 'next/link'
export default () => (
    <>
        <div>jspang - B页面</div>
        <Link href='/'>
            <a>返回首页</a>
        </Link>
    </>
)
  1. 编写首页
import React from 'react'
import Link from 'next/link'

const Home = () =>(
    <>
        <div>我是首页</div>
        <div><Link href='/jspangA'><a>去jspangA页面</a></Link></div>
        <div><Link href='/jspangB'><a>去jspangB页面</a></Link></div>
    </>
)
export default Home
注意点
  • Link标签中只能包含一个跟标签,不能有同级标签

2.编程式跳转

使用Router方法可以实现跳转页面

import React from 'react';
import Link from 'next/link';
import Router from 'next/router';

const Home = () =>{
    // 编写跳转方法
    function gotoA() {
        Router.push('/jspangA')
    }
    return (
      <>
        <div>我是首页</div>
        <div><Link href='/jspangA'><a>去jspangA页面</a></Link></div>
        <div><Link href='/jspangB'><a>去jspangB页面</a></Link></div>
        <div>
            <button onClick={gotoA}>jspangA</button>
        </div>
      </>
    )
}
export default Home

3.传参

路由式传参

query传参

将参数放在url进行传递

import React from 'react'
import Link from 'next/link'

// query传递参数 老版本next.js仅仅支持query传参
const Home = () =>{

    return (
      <>
        <div>我是首页</div>
        <div>
            <Link href="/chuancan?name=张三">
              <a>跳转</a>
            </Link>
        	// 第二种写法👇👇👇
            <Link href={{pathname:'/chuancan',query:{name:'李四'}}}> 
              <a>李四</a>
            </Link>
        </div>
      </>
    )

}
export default Home



//-----接收参数-----

import React from 'react'
import {withRouter} from 'next/router';// 需要使用 withRouter 进行加工
import Link from 'next/link'

const Chuancan = ({router})=>{
    return (
        <>
            <div>{router.query.name}</div>
            <Link href='/'><a>返回首页</a></Link>
        </>
    )
}

export default withRouter(Chuancan)

编程式传参

import React from 'react'
import Link from 'next/link'
import Router from 'next/router'

// query传递参数 老版本next.js仅仅支持query传参
const Home = () =>{

  function goto(){
    Router.push({
      pathname:'/chuancan',
      query:{
        name:'张三'
      }
    })
  }
    return (
      <>
        <div>我是首页</div>
        <div>
            <Link href="/chuancan?name=张三">
              <a>跳转</a>
            </Link>
        </div>
        <div>
          <button onClick={goto}>点击跳转并携带参数</button>
        </div>
      </>
    )

}
export default Home

Next中的组件

在components文件下创建jspang.js组件

export default ({children})=> {
    return (
      <button>
        {children}
      </button>
    )
}
//写一个简单的组件示例

在首页文件中导入

import Jspang from '../components/jspang' // 引入按钮组件
export default function Home() {
  return (
    <div>
      <Jspang>测试按钮组件</Jspang>
    </div>
  )
}

路由钩子事件

  • routeChangeStart 路由发生变化之前
  • routeChangeComplete 路由发生变化之后
  • beforeHistoryChange Next.js全部都用History模式
  • routeChangeError 路由发生错误时,404不算
  • hashChangeStart Hash路由切换之前
  • hashChangeComplete Hash路由切换完成
import React from 'react'
import Link from 'next/link'
import Router from 'next/router'

const Home = () =>{
  // routeChangeStart     路由发生变化之前
  // routeChangeComplete  路由发生变化之后
  // beforeHistoryChange  Next.js全部都用History模式
  // routeChangeError     路由发生错误时,404不算
  // hashChangeStart      Hash路由切换之前
  // hashChangeComplete   Hash路由切换完成

  Router.events.on('routeChangeStart',(...argus)=>{
      // ...argus 返回路径和{shallow: false}对象
      console.log('1.routeChangeStart,路由开始变化,参数为:',...argus);
  })
  Router.events.on('routeChangeComplete',(...argus)=>{
      // ...argus 返回路径和{shallow: false}对象
      console.log('2.routeChangeComplete,路由变化结束,参数为:',...argus);
  })
  Router.events.on('beforeHistoryChange',(...argus)=>{
      // ...argus 返回路径和{shallow: false}对象
      console.log('3.beforeHistoryChange,参数为:',...argus);
  })
  Router.events.on('routeChangeError',(...argus)=>{
      // ...argus 返回路径和{shallow: false}对象
      console.log('4.routeChangeError,路由发生错误时,参数为:',...argus);
  })
  Router.events.on('hashChangeStart',(...argus)=>{
      // ...argus 返回路径和{shallow: false}对象
      console.log('5.hashChangeStart,Hash路由切换之前,参数为:',...argus);
  })
  Router.events.on('hashChangeComplete',(...argus)=>{
      // ...argus 返回路径和{shallow: false}对象
      console.log('6.hashChangeComplete,Hash路由切换完成,参数为:',...argus);
  })
  function goto(){
    Router.push({
      pathname:'/chuancan',
      query:{
        name:'张三'
      }
    })
  }

    return (
      <>
        <div>我是首页</div>
        <div>
            <Link href="/chuancan?name=张三">
              <a>张三</a>
            </Link>
            <Link href={{pathname:'/chuancan',query:{name:'李四'}}}>
              <a>李四</a>
            </Link>
        </div>
        <div>
          <button onClick={goto}>点击跳转并携带参数</button>
        </div>
      </>
    )

}
export default Home

Next.js中使用Axios

getiInitialProps是 Next.js 最伟大的发明,它确定了一个规范,一个页面组件只要把访问 API 外部资源的代码放在 getInitialProps 中就足够,其余的不用管,Next.js 自然会在服务器端或者浏览器端调用getInitialProps来获取外部资源,并把外部资源以 props 的方式传递给页面组件。

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

const Chuancan = ({router,data})=>{ // 仅仅在withRouter下使用
    return (
        <>
            <div>{router.query.name}</div>
            <div>
                {
                    data.map(ele=>{
                        return <p key={ele.title}>{ele.title}</p>
                    })
                }
            </div>
            <Link href='/'><a>返回首页</a></Link>
        </>
    )
}

Chuancan.getInitialProps = async ()=>{
    const promise = new Promise((resolve)=>{
        axios('http://192.168.210.146:9527/api/goodList?page=1').then((res)=>{
            console.log('数据:',res);
            resolve(res)
        })
    })
    return await promise
}
export default withRouter(Chuancan)

使用Style jsx编写页面

import React,{useState} from 'react';

function Jspang() {
    const [color,setColor] = useState();
    
    const changeColor=()=>{
        setColor(color==='blue'?'red':'blue')
    }

    return (
        <>
            <div>测试文本</div>
            <div><button onClick={changeColor}>改变颜色</button></div>

            <style jsx>
                {`
                    div{color:${color};}               
                `}
            </style>
        </>
    )
}
export default Jspang

LazyLoading懒加载

外部库实现方式

采用异步引入的方式,仅在需要的时候引入使用

import React,{useState} from 'react';

function Time() {
    const [nowTime,setTime] = useState(Date.now())

    const changeTime = async ()=>{
        const moment = await import('moment') // 异步引入
        setTime(moment.default(Date.now()).format())
    }

    return (
        <>
            <div>显示时间:{nowTime}</div>
            <div><button onClick={changeTime}>改变时间格式</button></div>
        </>
    )
}

export default Time

自定义库

自定义一个组件

export default ()=><div>Lazy Loading ...</div>

引入next的dynamic

仅在使用的时候生效

import React,{useState} from 'react';
import dynamic from 'next/dynamic';

const One = dynamic(import('../components/one'));

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

自定义Head

为优化SEO,请求头是必不可少的,自定义请求头可以是SEO更加便捷找到页面

为方便可以将头做成组件,当然也可以每个页面使用不同的Head

使用Next提供的组件<Head/>

import Head from 'next/head'
const MyHeader = ()=>{
    return (
        <>
            <Head>
                <title>JSPang.com</title>
            </Head>
        </>
    )
}
export default MyHeader

在需要的时候引入

import MyHeader from "../components/myHeader"

export default function Header() {
  return (
    <>
      <MyHeader/>
      <div>Header</div>
    </>
  )
}

Next.js中使用css

Next中是无法正常引入css进行使用的,参考官方文档

  1. 在pages文件下新建_app.js
  2. 新建style.css全局样式文件
// _app.js

import './styles.css'; //你的全局css样式

export default function MyApp({Component,pageProps}){
    return <Component {...pageProps}></Component>
}
  1. 如果是组件的话可以在组件内引入
import 'antd/dist/antd.css'
import {Button} from 'antd'

export default function Header() {
  return (
    <>
      <Button>按钮</Button>
    </>
  )
}
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值