技術概述
什么情況下會使用到這個技術?
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
是否發生改變,如果改變,則更新狀態。通過以上的方法,來達到函數式組件的變更是否顯示導航欄的效果。