在碰到純前端的大專案時,專案內有許多頁面是必然的。都是在同個專案,當頁面跳轉時,想必也都會使用到相同的元件。但是,在創建新頁面時,我們不僅要複製多個元件,甚至是整個檔案 ── 如果要對單一元件(如:menu)進行修改,便需要對每一個檔案的該元件進行修改,不覺得這大幅降低了我們在撰寫專案的效率嗎?
而我們今天便是要向您展示,如何使用React的公共元件和頁面跳轉以避免上述的情況!
首先要提到的是,公共元件的切板,我們使用的設計是前幾天教過的header,詳情請參考 ⇒ 【Day19】常見切版應用(3-1)頁頂Header實作
在public資料夾內創建基本的檔案:
// Header.js
const Header = () => {
return (
<></>
)
}
export default Header;
將header.js創建完畢後,把第19天寫好的Header樣式貼上:
並把class全部改成className,而後將fontAwesome元件引入:
import "./Header.css";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faBars } from "@fortawesome/free-solid-svg-icons";
const Header = () => {
return (
<header>
<div className="container header">
<div className="header-logo" style={{color:"white"}}>
@ this is a logo
</div>
<div className="menu-link">
<a href="#page1">go page1</a>
<a href="#page2">go page2</a>
<a href="#page3">go page3</a>
<a href="#page4">go page4</a>
<a href="#page5">go page5</a>
</div>
<button className="menu-btn">
<FontAwesomeIcon icon={faBars} style={{color: "#ffffff",}} />
</button>
</div>
</header>
)
}
export default Header;
此處我們先把homePage的元件刪除,這樣比較好操作:
再來是RWD的部分,這部份我們需要對header加入幾種狀態:
上圖截自 ⇒ 【Day19】常見切版應用(3-1)頁頂Header實作
import "./Header.css";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faBars } from "@fortawesome/free-solid-svg-icons";
import { useEffect,useState,useRef } from "react";
import useRWD from "../useRWD.js";
const Header = () => {
const hamburger = useRef();
const menu = useRef();
const [menuStatus, setMenuStatus] = useState(false);
const menuClick = () => {
setMenuStatus(
function (prev) {
return !prev;
}
);
}
useEffect(() => {
if (menuStatus) {
menu.current.style.display = "flex";
} else {
menu.current.style.display = "none";
}
}, [menuStatus]);
return (
<header>
<div className="container header">
<div className="header-logo" style={{color:"white"}}>
@ this is a logo
</div>
<div className="menu-link" ref={menu}>
<a href="#page1">go page1</a>
<a href="#page2">go page2</a>
<a href="#page3">go page3</a>
<a href="#page4">go page4</a>
<a href="#page5">go page5</a>
</div>
<button className="menu-btn" ref={hamburger} onClick={menuClick} style={{color:"white"}}>
<FontAwesomeIcon icon={faBars} style={{color: "white"}} />
</button>
</div>
</header>
)
}
export default Header;
將按鈕事件處理妥當。
上面程式碼中,我們使用到了新的語法:useRef()
useRef()
的用法相當於jQuery的選擇器的概念,可以方便我們對DOM元件進行操作。
使用useRef()
的時候我們要先在前面宣告一個變數,才能往下面的元件加入ref的傳入值。
而要使用useRef()
得到此物件的DOM,則要使用 .current
語法才能拿到。
如下圖所示:
撰寫完畢後,當我們點擊按鈕時,便會有效果了:
但是會發現,當我們對頁面進行縮放時,還是會產生頁面的link區域不見的問題。
想要解決這個問題,我們必須去追蹤頁面的寬度,檢視當寬度變成多少時,需要作出變更。
所以我們要在public創建一個 useRWD.js
的檔案。
比較不同的是,這裡我們並不需要回傳元件,而是要回傳資料:
// global/useRWD.js
const useRWD = () => {
}
export default useRWD;
新增一個mobile的狀態,用來記錄是否為手機頁面:
import { useState,useEffect } from "react";
const useRWD = (pixel) => {
const [mobile,setMobile] = useState(false);
const handleRWD = () => {
if (window.innerWidth >=pixel){
setMobile(true)
} else {
setMobile(false)
}
}
}
export default useRWD;
使用 useEffect()
去追蹤mobile的狀態:
import { useState,useEffect } from "react";
const useRWD = (pixel) => {
const [mobile,setMobile] = useState(false);
const handleRWD = () => {
if (window.innerWidth >=pixel){
setMobile(true)
} else {
setMobile(false)
}
}
useEffect(()=>{
window.addEventListener('resize',handleRWD);
handleRWD();
return(()=>{
window.removeEventListener('resize',handleRWD);
})
},[]);
return mobile;
}
export default useRWD;
回到我們的 Header.js
,並把 useRWD()
加進去:
const device = useRWD(770);
useEffect(() => {
if (device) {
hamburger.current.style.display = "none";
menu.current.style.display = "flex";
} else {
hamburger.current.style.display = "block";
menu.current.style.display = "none";
}
}, [device])
完整代碼如下:
header完成了!
再來我們要做router的部分了:
欲使用router的部分,我們需要引入react的Link component,它的作用與 <a>
相似。
(這裡我為了Demo又再多加了幾個頁面)
接下來,我們要去下載一個包:React Router DOM ⇒ https://www.npmjs.com/package/react-router-dom
安裝完畢:
回到 index.js
,這裡我們需要引入React Router DOM的幾個元件:BrowserRouter, Routes, Route
並像下方展示的樣子把元件填進去:
而這裡對應的每個值便是您方才在header內寫的link值。
如此一來,我們的header便完成了!
切換到另一個頁面後,內容物也是一樣的:
由此往後延伸,您可以在元件的前面或後面添加些新的東西,就可以讓此元件一次出現在不同的頁面中:
那今天的教學就到這裡了,寫完之後是不是 ── 讓您不想繼續碰前端了呢?(誤
沒問題haha,因為明天我們將要進入到Python的部分!
「甚麼?Python也能寫網頁嗎?」沒錯!敬請期待接下來的篇章吧!
遇到一個問題很困擾,我使用 或是 useNavigate 跳轉頁面時 header 的 Token 不知如何設定,都會被塞入一個過期的 Token,導致驗證失敗無法產生內容,這部分該如何處理比較好?