2021鐵人賽
React
如Day15的wireframe,為了要加上更多的功能,因此要在頂端列新增幾個按鈕,每個按鈕代表不同的路由,而不同的路由會導引到不同的頁面。本篇就先做到點擊頂端列按鈕可以跳轉頁面吧!
首先打開terminal並切換至專案資料夾,並執行下面這行,就會安裝好套件了。
npm install react-router-dom
這邊還是使用react-bootstrap的Nav元件來製作連結按鈕,也就是下面程式碼的Nav.Link,目前先規劃首頁與總體經濟兩個頁面,先作到兩個路由可以切換為主。
src\components\Navbar\Navbar.js
import React from 'react';
import styles from './Navbar.module.css';
import Navbar from 'react-bootstrap/Navbar';
import svgIcon from './navbaricon.svg';
import Nav from 'react-bootstrap/Nav';
const Topbar = () => {
return (
<Navbar className={styles.navbar}>
<Navbar.Brand className={styles.title} href="/">
<img
alt=""
src={svgIcon}
width="30"
height="30"
className="d-inline-block align-top"
/>{' '}Invsetment Dashboard
</Navbar.Brand>
<Navbar.Collapse id="responsive-navbar-nav">
<Nav className="me-auto">
<Nav.Link href="/">首頁</Nav.Link>
<Nav.Link href="/macroeconomics">總體經濟</Nav.Link>
</Nav>
</Navbar.Collapse>
</Navbar>
);
};
export default Topbar;
做好後的畫面長這樣,上面有兩個按鈕,分別是首頁及總體經濟。
目前有兩個頁面分別是Home與Macroeconomics,先將這兩個分頁加到components資料夾內,首先在components內新增兩個資料夾:
其中Home資料夾內建立index.js檔,先簡單放個文字進去就好:
src\components\Home\index.js
import React from 'react';
const Home = () => {
return (
<React.Fragment>
<h1>Home</h1>
</React.Fragment>
);
};
export default Home;
一開始實作的總體經濟的頁面,要從App.js內獨立出來,放在Macroeconomics資料夾內,App.js只留下控制路由的功能。
src\components\Macroeconomics\index.js
import React, { useState } from 'react';
import Charts from "../Charts/Charts";
import Selector from '../Selector/Selector';
import charts from '../../data/chart-collections.json';
import releases from '../../data/releases.json';
import sources from '../../data/sources.json';
const Macroeconomics = () => {
const [filteredReleaseId, setFilteredReleaseId] = useState(0);
const [filteredSourceId, setFilteredSourceId] = useState(0);
const filteredCharts = charts.filter(chart => {
let filterd = false
if (filteredReleaseId === 0 && filteredSourceId === 0) { filterd = true }
if (filteredReleaseId === 0 && filteredSourceId !== 0) {
filterd = chart.source_id === filteredSourceId
}
if (filteredReleaseId !== 0 && filteredSourceId === 0) {
filterd = chart.release_id === filteredReleaseId
}
if (filteredReleaseId !== 0 && filteredSourceId !== 0) {
filterd = chart.release_id === filteredReleaseId && chart.source_id === filteredSourceId
}
return filterd
});
const releaseIdChangeHandler = (selectedReleaseId) => {
setFilteredReleaseId(selectedReleaseId);
};
const sourceIdChangeHandler = (selectedSourceId) => {
setFilteredSourceId(selectedSourceId);
};
return (
<React.Fragment>
<Selector
selectedReleaseId={filteredReleaseId}
selectedSourceId={filteredSourceId}
releases={releases}
sources={sources}
onReleaseIdChange={releaseIdChangeHandler}
onSourceIdChange={sourceIdChangeHandler}
/>
<Charts charts={filteredCharts} />
</React.Fragment>
);
};
export default Macroeconomics;
路由資料:詳細說明每一個路由對應的路徑及元件...等資料。
src\App-route.js
import Home from "./components/Home/index";
import Macroeconomics from "./components/Macroeconomics/index";
//
const routes = [
{
key: "route-home",
name: "home",
path: "/",
withHeader: true,
withFooter: true,
public: true, // 若在維護開發中請設定 false
authority: null,
component: Home,
},
{
key: "route-macroeconomics",
name: "macroeconomics",
path: "/macroeconomics",
withHeader: true,
withFooter: true,
public: true, // 若在維護開發中請設定 false
authority: null,
component: Macroeconomics,
}
];
export default routes;
路由層:將路由資料引入,並使用react-router-dom提供的元件撰寫路由層
src\routerLayer\index.js
import React from "react";
import { BrowserRouter as Router, Switch, Route, Link } from "react-router-dom";
import routes from "../App-route";
import Layout from "../layout";
const RouterLayer = () => {
return (
<Router>
<Switch>
{routes &&
routes
.filter((r) => r.public)
.map((route) => (
<Route exact key={route.key} path={route.path}>
<Layout {...route} />
</Route>
))}
</Switch>
</Router>
);
};
export default RouterLayer;
Layout:將頁面的基礎設定統一處理,例如header/body/footer的設定
src\layout\index.js
import React from "react";
import Header from "./header";
import Body from "./body";
const Layout = (props) => {
return (
<React.Fragment>
<Header />
<Body {...props} />
</React.Fragment>
);
};
export default Layout;
Layout的header設定,網頁的最上方是Navbar,因此直接拿來當header即可
src\layout\header\index.js
import React from "react";
import Navbar from "../../components/Navbar/Navbar";
const Header = () => {
return <Navbar />
}
export default Header;
Layout的body設定,這邊先不對body做設定,直接導入component
src\layout\body\index.js
import React from "react";
const Body = ({ component: Component }) => {
return (
<Component />
);
};
export default Body;
上面路由層的設定比較複雜一些,主要是因為想讓程式可擴充性及可管理性高一些,例如只要調整header及body的index.js檔案,就可以適用在各個路由的頁面。
上面的路由層寫好之後,就可以導入App.js了,如下程式碼,把整個路由架構寫在路由層內之後,App.js就會變得非常簡潔。
src\App.js
import React from 'react';
import './App.css';
import RouterLayer from "./routerLayer";
function App() {
return (
<div className="App">
<RouterLayer />
</div>
);
}
export default App;
本篇路由層參考其他專案架構,寫出一個比較可以維護的資料夾結構,也很感謝工程師朋友願意分享專案架構給我參考,跟React提供的basic版路由架構差蠻多的,學習到很多。下一篇就來製作首頁的wireframe吧。