iT邦幫忙

2024 iThome 鐵人賽

DAY 14
0
Modern Web

30天打造個人簡易旅遊網站系列 第 14

Day 14:使用 React 實現可收合的導航欄(Navbar)功能

  • 分享至 

  • xImage
  •  

這篇文章將指導您如何在 React 應用中創建一個可收合的導航欄。該導航欄在縮合時僅顯示圖標,展開時顯示完整的圖標和標題,提升使用者體驗。

目標

我們的目標是實現以下功能:

  1. 當導航欄縮合時,只顯示圖標。
  2. 當導航欄展開時,顯示完整的標題和圖標。
  3. 滑鼠懸停時導航欄展開,並保持良好的排版。

步驟 1:建立專案結構

首先,確保您的專案具有以下結構,以便於組件的管理:
src

├── components
│ ├── Header
│ │ ├── Header.jsx
│ │ └── header.module.css
│ ├── NavBar
│ │ ├── NavBar.jsx
│ │ └── navbar.module.css
└── assets
└── travel.png

專案結構說明

  • components:這個資料夾用來存放所有的 React 組件,這樣可以保持專案的結構清晰。
  • assets:用來放置圖片或其他靜態資源。

步驟 2:編寫 Header 組件

Header.jsx

在這個組件中,我們會使用 useState 來管理導航欄的縮合狀態,並透過滑鼠事件來切換狀態。有關useState後續的單元會詳細說明.

import { useState } from "react";
import styles from "./header.module.css";
import Logo from "../../assets/travel.png"; // 引入 Logo 圖片
import { Divider } from "antd"; // 引入 Ant Design 的 Divider
import NavBar from "../NavBar"; // 引入 NavBar 組件

export default function Header() {
  const [isShrink, setIsShrink] = useState(true); // 設定初始狀態為縮合

  return (
    <div
      className={`${styles.headerContainer} ${isShrink ? styles.shrink : styles.expand}`}
      onMouseEnter={() => setIsShrink(false)} // 滑鼠進入時展開
      onMouseLeave={() => setIsShrink(true)} // 滑鼠離開時縮合
    >
      <div className={styles.logoBox}>
        <img src={Logo} alt="logo" className={styles.logo} />
        {!isShrink && <h1 className={styles.title}>Travel</h1>} {/* 當未縮合時顯示標題 */}
        {!isShrink && <Divider className={styles.divider} />} {/* 當未縮合時顯示分隔線 */}
      </div>
      <NavBar isShrink={isShrink} /> {/* 傳遞狀態給 NavBar */}
    </div>
  );
}

解釋

  1. 狀態管理:
  • 使用 useState 設定 isShrink 來控制 Header 的縮合狀態,初始值為 true,表示預設為縮合狀態。
  1. 事件處理:
  • onMouseEnter 和 onMouseLeave 事件用來監聽滑鼠進入和離開 Header 的動作,當滑鼠進入時,狀態變為 false,導致 Header 展開;滑鼠離開時,狀態變回 true,Header 縮合。

header.module.css

.headerContainer {
  display: flex; /* 使用 Flexbox 排版 */
  flex-direction: column; /* 垂直排列 */
  align-items: center; /* 水平置中 */
  height: 100vh; /* 高度佔滿整個視窗 */
  padding: 1rem 0; /* 上下內邊距 */
  background-color: #282c34; /* 背景顏色 */
  transition: all 0.3s ease; /* 讓所有屬性都有平滑過渡效果 */
  width: 60px; /* 初始寬度 */
}

.expand {
  width: 200px; /* 展開時的寬度 */
}

.shrink {
  width: 60px; /* 縮合時的寬度 */
}

.logoBox {
  display: flex; /* 使用 Flexbox 排版 */
  flex-direction: column; /* 垂直排列 */
  align-items: center; /* 水平置中 */
  justify-content: center; /* 垂直置中 */
  margin-bottom: 1rem; /* 下邊距 */
  transition: all 0.3s ease; /* 讓所有屬性都有平滑過渡效果 */
}

.logo {
  width: 40px; /* 縮合時的 Logo 大小 */
  transition: width 0.3s ease; /* Logo 寬度過渡效果 */
}

.title {
  font-size: 16px; /* 縮合時的標題大小 */
}

.expand .logo {
  width: 80px; /* 展開時的 Logo 大小 */
}

.expand .title {
  font-size: 24px; /* 展開時的標題大小 */
}

.divider {
  border-color: #ffffff; /* 分隔線顏色 */
  opacity: 0; /* 縮合時隱藏分隔線 */
  transition: opacity 0.3s ease; /* 分隔線顯示過渡效果 */
}

.expand .divider {
  opacity: 1; /* 展開時顯示分隔線 */
}

解釋

  • Flexbox 排版:使用 Flexbox 使 Logo 和標題在垂直方向上對齊,並保持整體居中。
  • 過渡效果:透過 transition 為各種屬性添加平滑的過渡效果。
  • 顯示控制:使用條件渲染來控制標題和分隔線的顯示,確保在縮合狀態下不顯示它們。

步驟 3:編寫 NavBar 組件

NavBar.jsx

在這個組件中,根據 isShrink 狀態來顯示或隱藏導航項目的標題。

import styles from "./navbar.module.css";

const NavBar = ({ isShrink }) => {
  return (
    <div className={styles.navContainer}>
      <div className={styles.navbox}>
        <div className={styles.icon}>🏠</div>
        {!isShrink && <div className={styles.title}>Home</div>} {/* 當未縮合時顯示標題 */}
      </div>
      <div className={styles.navbox}>
        <div className={styles.icon}>📍</div>
        {!isShrink && <div className={styles.title}>Destinations</div>} {/* 當未縮合時顯示標題 */}
      </div>
      {/* 添加其他導航項目 */}
    </div>
  );
};

export default NavBar;

解釋

  1. 條件渲染:
  • 使用 {!isShrink && Home} 來控制標題的顯示,當導航欄縮合時,標題將不會顯示。

navbar.module.css

.navContainer {
  display: flex; /* 使用 Flexbox 排版 */
  flex-direction: column; /* 垂直排列 */
  align-items: center; /* 水平置中 */
  width: 60px; /* 初始寬度 */
  overflow: hidden; /* 隱藏溢出的內容 */
  transition: width 0.3s ease; /* 寬度過渡效果 */
}

.navContainer:hover {
  width: 200px; /* 滑鼠懸停時展開的寬度 */
}

.navbox {
  display: flex; /* 使用 Flexbox 排版 */
  align-items: center; /* 垂直置中 */
  justify-content: center; /* 水平置中 */
  width: 100%; /* 佔滿整個寬度 */
  padding: 0.5rem 1rem; /* 內邊距 */
  border-radius: 8px; /* 邊角圓弧 */
  transition: background-color 0.3s ease; /* 背景顏色過渡效果 */
  margin: 0.5rem 0; /* 上下邊距 */
}

.navbox:hover {
  background-color: rgba(188, 196, 249, 0.5); /* 懸停時背景顏色 */
}

/* Icon 的樣式 */
.icon {
  display: flex;
  justify-content: center; /* 水平置中 */
  align-items: center; /* 垂直置中 */
  width: 100%; /* 確保寬度填滿 */
}

/* Title 的樣式 */
.title {
  font-size: larger; /* 標題字型大小 */
  color: aliceblue; /* 標題顏色 */
  white-space: nowrap; /* 不換行 */
}

.navbox .title {
  display: none; /* 縮合時隱藏標題 */
}

.navContainer:hover .navbox .title {
  display: inline-block; /* 懸停時顯示標題 */
}

解釋

  • Flexbox 排版:透過 Flexbox 使導航項目在水平和垂直方向上對齊,保持整體的一致性。
  • 顯示控制:在縮合時隱藏標題,而在滑鼠懸停時顯示標題,這樣用戶可以獲得更好的導航體驗。

步驟 4:整合和測試

將所有組件整合,並啟動應用程序來測試縮合和展開的功能是否正常運作。

npm run dev

https://ithelp.ithome.com.tw/upload/images/20240927/20169447Uha7TrxKem.pnghttps://ithelp.ithome.com.tw/upload/images/20240927/20169447s6WuM2N19O.png


上一篇
Day 13 :製作Navbar
下一篇
Day 15:如何在 React 應用中使用 Ant Design 的 FloatButton 進行導航
系列文
30天打造個人簡易旅遊網站30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言