iT邦幫忙

2021 iThome 鐵人賽

DAY 18
0
Modern Web

用React刻自己的投資Dashboard系列 第 18

用React刻自己的投資Dashboard Day18 - 選單列active style功能

tags: 2021鐵人賽 React

上一篇將選單列做出來,並且完成點擊上方按鈕會跳轉至對應頁面的功能,不過總覺得好像少了些什麼?原來是點擊按鈕之後,按鈕的樣式沒有跟著改變,會讓使用者不知道目前到底是在哪一個頁面,而所謂跟著點擊動作改變按鈕樣式的功能就稱為active。

說起來這個功能是非常簡單的,不過也是弄了蠻久,因為架構上的不熟悉以及使用react-bootstrap套件,要動態調整按鈕的active樣式變得有點困難,研究了技術文件許久才知道怎麼寫,下面就把這個過程記錄下來。

期望達成的效果

React-Bootstrap內建activeKey功能

看了一下react-bootstrap官方文件,發現Nav這個component有內建activeKey功能:

Name Type Description
activeKey string / number Marks the NavItem with a matching eventKey (or href if present) as active.

也就是說,可以使用eventKey或是href去替NavItem加上active class。使用方式如下:

目前activeKey指到/home這個路徑,那home這個NavItem就會多一個active class,所以只要可以隨著所在的路徑動態改變activeKey,就可以更動active class的位置。

<Nav
  activeKey="/home"
>
  <Nav.Item>
    <Nav.Link href="/home">Active</Nav.Link>
  </Nav.Item>
  <Nav.Item>
    <Nav.Link eventKey="link-1">Link</Nav.Link>
  </Nav.Item>
  <Nav.Item>
    <Nav.Link eventKey="link-2">Link</Nav.Link>
  </Nav.Item>
  <Nav.Item>
    <Nav.Link eventKey="disabled" disabled>
      Disabled
    </Nav.Link>
  </Nav.Item>
</Nav>

傳遞路徑至Navbar

那要怎麼動態改變activeKey呢?只要透過props將路徑傳遞給Navbar這個元件即可。因為這次傳遞路徑的架構稍微複雜了一些,所以透過props傳遞好幾層才到Navbar。

過程由上而下大概是這樣:

  • 從App.js導入路由層RouteLayer
    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;

  • 路由層將路徑資料傳遞給Layout
    src/routerLayer/index.js
import React from "react";
import { BrowserRouter as Router, Switch, Route } 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
    src/layout/index.js
import React from "react";
import Header from "./header";
import Body from "./body";

const Layout = (props) => {
  return (
    <React.Fragment>
      <Header {...props} />
      <Body {...props} />
    </React.Fragment>
  );
};

export default Layout;
  • Header將路徑資料傳遞給Navbar
    src/layout/index.js
import React from "react";
import Navbar from "../../components/Navbar/Navbar";

const Header = (props) => {
  return <Navbar {...props} />
}

export default Header;
  • Navbar內使用props.path讀取路徑資料
    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 = (props) => {
  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" activeKey={props.path}>
          <Nav.Link href="/" className={styles.link}><p>首頁</p></Nav.Link>
          <Nav.Link href="/macroeconomics" className={styles.link}><p>總體經濟</p></Nav.Link>
        </Nav>
      </Navbar.Collapse>
    </Navbar>
  );
};

export default Topbar;

小結

總之繞了好一大圈,終於將路徑資料傳遞到Navbar裡面了,架構上看起來稍微複雜了一些,不過是為了後續維護上的方便度,才使用這樣的架構,還算是可以接受。目前首頁還是沒有內容的,接下來就來做一下首頁吧~


上一篇
用React刻自己的投資Dashboard Day17 - Dashboard 2.0版路由功能
下一篇
用React刻自己的投資Dashboard Day19 - 2.0版首頁內容設計
系列文
用React刻自己的投資Dashboard30

尚未有邦友留言

立即登入留言