公共布局Layouts
React 开发页面是由一系列的组件构成,其中许多组件经常在页面之间重复使用。比如,每一页上都有相同的导航栏和页脚。因此,可以再next中进行公共部分内容的封装,可以分为全局Layouts和局部Layouts。
- 在项目的
src
目录下,新建layouts
目录,用于保存各种布局文件
1. pages/* 目录下的 layouts 组件
如果整个应用程序只有一个全局公共布局,则可以创建一个
_app.jsx
并将layouts布局放在自定义app中。由于<Layout/>组件在更改页面时会被重复使用,因此其组件状态将被保留(例如输入值)。注意:这个全局布局组件会作用于pages
目录下的所有组件,而app/page.jsx
的项目入口页面并不会加载这个组件。
1.1 创建 layouts 文件
- 在
src
目录下新建layouts
目录,并创建global.jsx
和global.module.scss
文件 - 在
global.jsx
中配置layouts布局内容import styles from "./global.module.scss"; import Link from "next/link"; export default function GlobalLayouts(props) { return ( <div className={styles.GlobalLayouts}> {props.children} <div className="footer"> <Link href="/home?id=1">首页</Link> <Link href="/profile/200">我的</Link> </div> </div> ); }
- 在
global.module.scss
文件中设置样式.GlobalLayouts { :global { .footer { cursor: pointer; display: flex; height: 100px; justify-content: space-around; align-items: center; position: fixed; left: 0; bottom: 0; width: 100vw; } } }
1.2 在 _app.jsx 中使用全局 layouts
- 修改
_app.jsx
文件import GlobalLayouts from "../layouts/global"; function App({ Component, pageProps }) { const [locale, setLocale] = useState("zhCN"); const [themeColor, setThemeColor] = useState("orange"); return ( <GlobalLayouts> <ConfigProvider> ... // _app.js 中的内容 <Component {...pageProps} /> </ConfigProvider> </GlobalLayouts> ); } export default App;
2. app/* 目录下的 layouts 组件
_app.jsx
中配置的layouts
组件,只会作用于pages
目录下的组件,而app/page.jsx
页面有属于自己的layout
组件文件,即同目录下的layout.js
文件,该文件只针对app/page.jsx
生效,其它页面不生效。
- 修改
app/layouts.js
文件,保存即生效export const metadata = { title: "首页", description: "Generated by create next app", }; export default function RootLayout({ children }) { return ( <html lang="en"> <body> <h1>app/pages.jsx布局组件</h1> {children} </body> </html> ); }
3. 页面隐藏全局 layouts
一般情况下,全局
layouts
是在整个页面切换期间始终存在的,加入个别页面不需要显示这个公共的layouts
组件内容,可以在使用layouts
组件的时候,通过条件渲染实现按需显示。
- 修改
_app.jsx
文件import GlobalLayouts from "../layouts/global"; function App({ Component, pageProps }) { // Component.name 属性可以获取要加载的页面组件的名称。可以通过该名称判断该组件是否需要公共 layouts 内容。 return ( <GlobalLayouts showTab={["Profile"].indexOf(Component.name) !== -1 ? false : true}> <ConfigProvider> ... <Component {...pageProps} title="额外的数据" /> </ConfigProvider> </GlobalLayouts> ); } export default App;
4. 基于单个页面的 layouts 组件
如果您需要多个不同的
layouts
布局,您可以在单个页面组件中为组件添加一个属性getLayout,该属性是一个函数,其内部返回一个React组件。这样做可以让您在每页的基础上定义布局。
- 新建
layouts/slider.jsx
文件export default function SliderLayouts(props) { return ( <div className="Slider"> {props.children} <div className="s"> <h5>首页</h5> <h5>我的</h5> <h5>购物车</h5> </div> </div> ); }
- 修改
pages/profile/[id].jsx
文件,配置SliderLayouts组件import _JSXStyle from "styled-jsx/style"; import SliderLayouts from "@/layouts/slider"; export default function Profile() { return ( <div className="Profile"> <h4>个人中心</h4> <p>段落</p> <_JSXStyle>{` .Profile { margin: 50px 0; > h4 { text-align: center; background-color: lightblue; height: 200px; } } // 在这里设置SliderLayouts组件的样式 .Slider > .s { position: fixed; top: 200px; left: 0px; width: 50px; background-color: blue; > h5 { height: 50px; text-align: center; line-height: 50px; } } `}</_JSXStyle> </div> ); } Profile.getLayout = function getLayout(page) { return <SliderLayouts>{page}</SliderLayouts>; };
- 修改
_app.jsx
文件,将getLayout
函数应用到页面上function App({ Component, pageProps }) { ... // 获取当前的组件是否含有 getLayout 函数 const getLayout = Component.getLayout || ((page) => page); return ( <GlobalLayouts showTab={["Profile"].indexOf(Component.name) !== -1 ? false : true}> <ConfigProvider> ... // 调用getLayout函数,将要展示的页面作为参数传递进去 {getLayout(<Component {...pageProps} title="额外的数据" />)} </ConfigProvider> </GlobalLayouts> ); }
- 刷新页面,即可看到单页面的
layouts
布局生效。