挑戰目標: MockNative Camp前端
週末也是很多事要做,每天大概都晚上9點到12點是鐵人賽的工作時間,寫code, test, debug和截圖之後才開始寫文章,真的是每天都像在趕末班電車,太慘LA。
今天要做的是
當hover 時會出現下面的東西,這個我會將下面會展開的東西通通寫進去config中,
next.config.js
module.exports = {
images: {
domains: ['nativecamp.net'],
minimumCacheTTL: 60,
},
publicRuntimeConfig: {
navTab: [
{ name: "首頁", image: "https://nativecamp.net/user/images/gnavi/ic_home.svg", imageHov: "https://nativecamp.net/user/images/gnavi/ic_home-h.svg" },
{ name: "指南", image: "https://nativecamp.net/user/images/gnavi/ic_guide.svg", imageHov: "https://nativecamp.net/user/images/gnavi/ic_guide-h.svg" },
{ name: "學習", image: "https://nativecamp.net/user/images/gnavi/ic_study.svg", imageHov: "https://nativecamp.net/user/images/gnavi/ic_study-h.svg" },
{ name: "搜尋・預約講師", image: "https://nativecamp.net/user/images/gnavi/ic_search.svg", imageHov: "https://nativecamp.net/user/images/gnavi/ic_search-h.svg" },
{ name: "其他", image: "https://nativecamp.net/user/images/gnavi/ic_etc.svg", imageHov: "https://nativecamp.net/user/images/gnavi/ic_etc-h.svg" },
],
navDetails: {
"首頁": [],
"指南": [
{
"name": "使用方法",
"list": ["致初次使用者", "使用方法", "關於上課不限堂數"]
},
{
"name": "收費・套餐",
"list": ["關於費用"]
},
{
"name": "使用環境",
"list": ["支援的瀏覽器", "關於英語會話APP"]
}
], "學習": [
{
"name": "教材",
"list": ["瀏覽教材", "課程及教材診斷", "線上商店 (教材購買)"]
},
{
"name": "精選教材",
"list": ["Callan Method(凱倫學習法)", "TOEIC®L&R TEST對策"]
},
{
"name": "自學內容",
"list": ["口說測驗", "口語訓練"]
}
], "搜尋・預約講師": [{
"name": "講師介紹",
"list": ["講師一覽", "排名", "評論"]
},
{
"name": "關於講師",
"list": ["關於母語人士", "關於卡通人物講師"]
},
], "其他": [{
"name": "推薦內容",
"list": ["問卷結果 / 會員的心聲"]
},
{
"name": "其他",
"list": ["上課環境測試", "FAQ (聯絡我們)", "網站導覽"]
},
]
}
}
}
然後在header.js中設定選定tab的useState,把set func以props傳進去Nav.js和NavTab.js中,在hover時set tab state為該tab name,因為傳了兩層props很痛苦,之後會用Redux去做優化,我在寫Vue時也遇過要一直傳props的方式加上如果還要commit就會很麻煩,所以我只要可以復用的或是兩個以上component會用到的我一律都用Vuex去處理。
header.js 這邊宣吿了tab的useState,並將setTab以props傳入Nav
import Image from "next/image";
import Nav from "./Nav";
import { useState } from "react"
import NavDetail from "./NavDetail";
function Header() {
// control nav detail
const [tab, setTab] = useState("");
return (
<header >
<div className="bg-nativeCamp-header-bg h-header flex justify-center items-center">
<div className="flex items-center">
{/* Left */}
<div className=" m-auto py-4 pr-80">
<div className="relative flex h-logo cursor-pointer my-auto">
<Image
src="https://nativecamp.net/user/images/common/logo_s-zh-tw.png?v=2.1"
layout="fill"
objectFit="contain"
objectPosition="left"
/>
</div>
<h1 className="text-white text-headerLogo">
線上英語會話的NativeCamp.7天免費體驗進行中!
</h1>
</div>
{/* Right */}
<div className=" pl-80 mb-4 space-y-2">
<ul className="flex justify-end ">
<li>
<a
className="text-white text-sm hover:text-opacity-75"
href="https://nativecamp.net/zh-tw/tutors"
>
FOR TUTORS
</a>
</li>
</ul>
<ul className="flex space-x-2">
<li>
<a className='bg-nativeCamp-header-signup hover:bg-nativeCamp-header-signupHov text-white text-center text-xs py-2 px-6 rounded-sm cursor-pointer'>註冊</a>
</li>
<li>
<a className='bg-nativeCamp-header-login hover:bg-nativeCamp-header-loginHov text-white text-center text-xs py-2 px-6 rounded-sm cursor-pointer'>登入</a>
</li>
<li>
<a className="bg-transparent hover:border-opacity-75 border border-bg-white text-white text-center text-xs p-2 px-4 rounded-sm cursor-pointer">重新加入</a>
</li>
</ul>
</div>
</div>
</div>
{/* Nav */}
<div>
<Nav setTab={setTab} />
</div>
{/* Nav detail */}
<div>
<NavDetail tab={tab} />
</div>
</header>
);
}
export default Header;
Nav.js 因為判斷在哪邊hover所以還要將setTab再傳一層,很麻煩
import getConfig from 'next/config'
import NavTab from './NavTab'
function Nav({ setTab }) {
const { publicRuntimeConfig } = getConfig();
return (
<div className="">
<ul className="flex flex-row items-center justify-center pt-2 border-b">
{publicRuntimeConfig.navTab?.map(({ image, imageHov, name }) => (
<NavTab key={name} image={image} imageHov={imageHov} name={name} setTab={setTab} />
))}
</ul>
</div>
)
}
export default Nav
NavTab.ja 這邊在onMouseEnter時去呼叫setTab將tab name放進去
import { useState } from 'react';
import Image from "next/image";
function NavTab({ image, imageHov, name, setTab }) {
const [isHovering, setIsHovered] = useState(false);
const onMouseEnter = () => {
setIsHovered(true)
setTab(name)
};
const onMouseLeave = () => setIsHovered(false);
return (
<li className="w-48 flex items-center justify-center cursor-pointer text-nativeCamp-nav-text hover:text-nativeCamp-nav-textHov border-b-4 border-white hover:border-nativeCamp-nav-textHov"
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}>
<div className="space-y-2 w-48 flex justify-center items-center flex-col">
<div className="relative flex h-[28px] w-[28px]">
{isHovering ? (
<Image
src={imageHov}
layout="fill"
objectFit="contain"
/>
) : (
<Image
src={image}
layout="fill"
objectFit="contain"
/>
)}
</div>
<div className="pb-2" >
<span className="text-sm">{name}</span>
</div>
</div>
</li>
)
}
export default NavTab
NavDetail.js 這邊我們不先做CSS先看一下是否有成功
import getConfig from 'next/config'
function NavDetail({ tab }) {
const { publicRuntimeConfig } = getConfig();
return (
<div>
{publicRuntimeConfig.navDetails[tab]?.map(({ name, list }) =>
(<div>{name}
<p>{list}</p>
</div>)
)}
</div>
)
}
export default NavDetail
很好,成功了,明天在來把CSS給完成。