React基于Router的导航栏显示
技术概述
什么情况下会使用到这个技术?
React需要在主页面基于Router获取当前的路由,并变更是否显示类似导航栏之类的组件。
学习该技术的原因
在利用React框架做页面设计的时候,一般不是所有的页面都需要导航栏,这种情况下就可以使用这种方式来进行判断。
技术的难点在哪里?
React有类组件和函数组件模式,基于不同的组件,可以使用的方法不一样。而且,有些方法容易出现bug。
技术详述
流程图
类组件
1. 在app.jsx
中获取到当前路由
const { pathname } = this.props.history.location
2. 通过对获取到的路由进行判断是否显示导航栏
return (
<div>
<Switch>
<RouteAuth />
</Switch>
{pathname.indexOf('main') === -1 ? '' : <MainTabBar pathname={pathname} />}
</div>
)
3. 使this.props
含有路由参数
// App.jsx
export default withRouter(App);
// index.js
<Router>
<App />
</Router>
由于
app.jsx
这个页面是由浏览器直接打开的,所以在使用this.props
时,获取到的数据是为空的。(详细如下)
通过
withRouter
包裹后,类似于:
// 将组件包裹进 Route, 然后返回
const withRouter = () => {
return () => {
return <Route component={App} />
}
}
之后通过
this.props
可以获取到内容。并且,在使用了withRouter
之后,需要把BrowserRouter
放在index.js
中,否则就会报错。(详细如下)
函数式组件
1. 将layout
部分单独抽离出来
P.S.:当然,不抽离出来也是OK的
2. 通过useLocation
获取到当前的路由,并用useEffect
监听
// index.jsx
import { Layout as ALayout } from "antd";
import { useEffect, useState } from "react";
import { useLocation } from "react-router-dom";
import Sidebar from "../sidebar/index";
const { Content, Sider } = ALayout;
const Layout = ({ children }) => {
const { pathname } = useLocation();
const [showSidebar, setShowSideBar] = useState(false);
const [collapsed, setCollapsed] = useState(false);
useEffect(() => {
console.log(pathname);
setShowSideBar(pathname.indexOf("login") === -1);
}, [pathname]);
const hanldeCollapse = (collapsed) => {
setCollapsed(collapsed);
};
return (
<ALayout className="alayout" style={{ minHeight: "100vh" }}>
{showSidebar && (
<Sider collapsible collapsed={collapsed} onCollapse={hanldeCollapse}>
<Sidebar />
</Sider>
)}
<Content>{children}</Content>
</ALayout>
);
};
export default Layout;
3. 在Layout组件
中放入需要路由的组件
function App() {
return (
<div className="App">
<Router basename={process.env.PUBLIC_URL}>
<Layout>
<Switch>
<RouteAuth />
</Switch>
</Layout>
</Router>
</div>
);
}
技术使用中遇到的问题和解决过程
- 在
App.jsx
中无法使用useLocation
,会报错无法找到location
这个对象。至于解决方法,额,目前没找到,只能放弃。 - 如果使用
useHistory
来获取pathname
的方式,只有在页面刷新的时候,才会重新获取pathname
的值。额,目前也没有找到方法解决。
总结
就我使用情况来说,觉得函数式的组件更优于类组件。使用函数式组件的话,还可以利用
Antd
的layout布局
进行封装。通过使用react-router-dom
中的useLocation
进行获取路由,并使用useEffect
来监听其中的pathname
是否发生改变,如果改变,则更新状态。通过以上的方法,来达到函数式组件的变更是否显示导航栏的效果。