Next.js 13 项目中的多布局使用方法,你应该要会

原文:Next.js 13 项目中的多布局使用方法,你应该要会 - 掘金

一、需求讲解

在项目编写过程中,有可能会遇到这样的需求,在/app/demo01中需要有侧边栏,在同级目录下/app/demo02中不需要侧边栏,或者不需要侧边栏需要头部,这样的需求,我们就不能单单的靠一个Layout文件来使用。

1.1、/app/demo01(有侧边栏,没有header)

image-20230621183728006

1.2 /app/demo02(没有侧边栏,有header)

image-20230621183803721

1.3、/app/demo03(有侧边栏,有header)

image-20230621183954766

二、实现讲解

注意📢:本文主要以NextJs为主,所以讲解的是NextJs的实现

2.1、NextJs12的实现方式

本文主要以NextJs13为主,所以NextJs12只是略微带过。

首先在NextJs12以前,我们可以实现类似的需求,但是相对来说比较麻烦,因为是嵌套的,相当于你需要侧边栏,那么被侧边栏的Layout包裹的所有页面都会有有这个侧边栏,如果某个页面不需要这个侧边栏只能通过js去控制侧边栏的显示。

大概得实现方式:

在Layout组件中,同时写<Asider/><Header/>,通过监听路由的变化去指定显示,例如指定/app/demo01只显示<Asider/>

NextJs12简单实现如下
 

typescript

复制代码

import { useRouter } from 'next/router' import React, { memo, useEffect, useMemo, useState } from 'react' ​ const AsiderAndHeaderLayout = ({ children }: { children: React.ReactNode }) => {  const router = useRouter()  const [isShowAside, setIsShowAside] = useState<boolean>(true)  const [isShowHeader, setIsShowHeader] = useState<boolean>(true)  const asidePaths = ["/app/demo01"]  const headerPaths = ["/app/demo02"]  const asiderAndHeaderPaths = ["/app/demo03"]  useEffect(() => {    const path = router.pathname;    if (asidePaths.includes(path)) {      setIsShowAside(true)   } else if (headerPaths.includes(path)) {      setIsShowHeader(true)   } else if (asiderAndHeaderPaths.includes(path)) {      setIsShowAside(true)      setIsShowHeader(true)   } }, [router])  const ContainerHeight = useMemo(() => {    return isShowHeader ? "h-[calc(100vh-60px)]" : "h-screen" }, [isShowHeader])  return (    <div className='w-full h-screen flex flex-col'>     {isShowHeader && <div className='w-full h-[60px] bg-green-500'>Header</div>}      <div className={`w-full flex ${ContainerHeight}`}>        {isShowAside && <div className='flex-[320px_0_0] bg-blue-300'>Aside</div>}        <div className='flex-1'>{children}</div>      </div>    </div>  ) } ​ export default memo(AsiderAndHeaderLayout)

2.2、NextJs13的实现方式

在使用NextJs13的方法之前,我们需要先了解NextJs13的两个新特性

2.2.1、在NextJs13的App目录下,每个页面都有一个Layout.tsx的布局文件,但是不需要每个页面都设置,如果页面文件夹下有Layout.tsx文件才会走页面的Layout布局

image-20230621185810850

但是如图所示,如果页面的上一级设置了Layout布局,则会在上一次布局的基础上再嵌套一个Layout布局

2.2.2、在NextJs13中支持在App目录下创建(name)以括号的形式命名的文件目录,该文件不会作为路由

如图所示

image-20230621191029160

当前目录下共有三个页面//demo03/demo04,所以在以括号括起来的文件夹将不会渲染为路由,相当于下图的路径

image-20230621191400227

回到正题,我们熟悉了上面两个新特性后,这样我们就会明白其实需要不同的Layout只需要有不同的带()的文件夹而已,带括号的文件夹虽然不会被渲染成路由,但是同样也是拥有和页面一样的目录组成,可以给()文件夹单独设置layout.tsxloading.tsx以及error.tsx文件夹,这样在()号目录文件夹下的全部具有就会有layout布局。

即我们需要实现开头说的需求,只需要设置不同的带()的文件夹即可实现

image-20230621191948110

代码实现如下

目录结构

 

scss

复制代码

丨-app 丨--(asider) ---只显示侧边栏布局 丨----layout.tsx 丨----demo01 丨——————page.tsx 丨--(header)---只显示Header布局 丨----layout.tsx 丨----demo02 丨------page.tsx 丨--(asiderAndHeader)---显示侧边栏布局和Header布局 丨----layout.tsx 丨----demo03 丨------page.tsx

 

typescript

复制代码

// (asider)的Layout.tsx import React from 'react' ​ const layout = ({ children }: { children: React.ReactNode }) => {  return (    <div className='w-full h-screen flex'>      <div className='flex-[327px_0_0] bg-gray-500 text-white'>aside</div>      <div className='flex-1'>       {children}      </div>    </div> ) } ​ export default layout

 

typescript

复制代码

// (header)的Layout.tsx import React from 'react' ​ const HeaderLayout = ({ children }: { children: React.ReactNode }) => {  return (    <div className='w-full h-screen flex flex-col'>      <div className='flex-[70px_0_0] bg-gray-500 text-white'>Header</div>      <div className='flex-1'>{children}</div>    </div> ) } ​ export default HeaderLayout

 

typescript

复制代码

// (asiderAndHeader)的Layout.tsx import React, { memo } from 'react' ​ const AsiderAndHeaderLayout = ({children}:{children:React.ReactNode}) => {  return (    <div className='w-full h-screen flex flex-col'>      <div className='w-full h-[60px] bg-green-500'>Header</div>      <div className='w-full h-[calc(100vh-60px)] flex'>        <div className='flex-[320px_0_0] bg-orange-300'>Aside</div>        <div className='flex-1'>{children}</div>      </div>    </div> ) } ​ export default memo(AsiderAndHeaderLayout)

总结

通过上面的代码,我们就可以很容易的实现需要Aside或者需要Header或者需要AsiderHeader的布局效果。当让这也只是我的一己之见,我也是相当于初接触NextJs13的App全新布局,有什么地方有问题或者有其他的方案的,欢迎大家评论区讨论。

本文使用的代码已上传到github,地址github.com/izz520/Next…

我是YaSol,一个区块链行业的前端开发小菜鸡。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值