React Layout组件实现、路由隐藏头尾及useMediaQuery响应式适配问题
1、特定页面不渲染公共头尾的实现方案
有两种常用的实现方式,可根据项目规模选择:
方案1:通过Layout组件props控制(适合小型项目)
给Layout组件增加可选的显示控制参数,默认显示头尾,需要隐藏的页面主动传入false即可:
// components/Layout/Layout.tsx import Header from "./Header/Header" import Footer from "./Footer/Footer" interface LayoutProps { children: React.ReactNode // 新增控制参数,默认值为true showHeader?: boolean showFooter?: boolean } const Layout = ({ children, showHeader = true, showFooter = true }: LayoutProps) => { return ( <div className="layout-container"> {/* 满足条件才渲染对应组件 */} {showHeader && <Header />} {/* 页面主体用main标签包裹,符合HTML语义规范 */} <main className="page-content"> {children} </main> {showFooter && <Footer />} </div> ) } export default Layout
不需要显示头尾的页面使用方式:
// 以登录页为例 import Layout from "../components/Layout/Layout" import LoginContainer from "../containers/Login/LoginContainer" const LoginPage = () => { return ( <Layout showHeader={false} showFooter={false}> <LoginContainer /> </Layout> ) } export default LoginPage
方案2:通过路由元信息统一控制(适合中大型项目,路由集中管理的场景)
如果项目用了React Router等路由库,可以在路由配置里加meta字段标记页面是否需要显示头尾,Layout中自动读取当前路由配置判断,不需要每个页面单独传参:
// 路由配置文件示例(React Router v6) const routes = [ { path: '/', element: <HomePage />, meta: { showHeader: true, showFooter: true } }, { path: '/login', element: <LoginPage />, meta: { showHeader: false, showFooter: false } }, // 其他路由配置 ] // 改造Layout组件自动读取路由配置 import { useLocation } from 'react-router-dom' const Layout = ({ children }: { children: React.ReactNode }) => { const location = useLocation() // 匹配当前路由的meta配置 const currentRouteMeta = routes.find(route => route.path === location.pathname)?.meta || {} const { showHeader = true, showFooter = true } = currentRouteMeta return ( <div className="layout-container"> {showHeader && <Header />} <main className="page-content">{children}</main> {showFooter && <Footer />} </div> ) }
2、Layout中使用useMediaQuery实现响应式适配的说明
完全可以在Layout组件中使用useMediaQuery钩子做响应式适配,Layout作为全局布局容器,在这里统一处理不同设备的布局逻辑非常合理。
你可以直接使用第三方UI库提供的useMediaQuery钩子,也可以自定义简单的钩子实现:
// 自定义useMediaQuery钩子 import { useState, useEffect } from 'react' function useMediaQuery(query: string): boolean { const [matches, setMatches] = useState(false) useEffect(() => { const mediaQuery = window.matchMedia(query) // 初始化赋值 setMatches(mediaQuery.matches) // 监听屏幕尺寸变化 const handleChange = (e: MediaQueryListEvent) => setMatches(e.matches) mediaQuery.addEventListener('change', handleChange) return () => mediaQuery.removeEventListener('change', handleChange) }, [query]) return matches } // Layout中使用示例 const Layout = ({ children, showHeader = true, showFooter = true }: LayoutProps) => { // 判断当前设备是否为移动端(宽度小于768px) const isMobile = useMediaQuery('(max-width: 767px)') return ( <div className={`layout-container ${isMobile ? 'mobile-layout' : 'pc-layout'}`}> {showHeader && <Header isMobile={isMobile} />} <main className="page-content">{children}</main> {showFooter && <Footer isMobile={isMobile} />} </div> ) }
你可以根据拿到的isMobile变量,调整全局布局样式、向头尾组件传递响应式参数,比如移动端隐藏Header的导航菜单、改为汉堡按钮,调整内容区的内边距等,都可以在这里统一处理。
内容的提问来源于stack exchange,提问作者sunpl13
相关产品推荐
相关产品推荐

