[Day 10]怎麽每天都像在赶末班电车R(前端篇)

挑战目标: MockNative Camp前端


周末也是很多事要做,每天大概都晚上9点到12点是铁人赛的工作时间,写code, test, debug和截图之後才开始写文章,真的是每天都像在赶末班电车,太惨LA。

今天要做的是
https://ithelp.ithome.com.tw/upload/images/20210925/201403585CcECcuUrr.png
当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.jsNavTab.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

https://ithelp.ithome.com.tw/upload/images/20210925/20140358DFwInvrLpf.png
很好,成功了,明天在来把CSS给完成。


<<:  Day 10 Prototype 制作 - 版面、字体、间距、图示设定小技巧分享

>>:  Day10. 人与人之间偶有摩擦,物体与物体之间叫做碰撞 - Collision(上)

成为工具人应有的工具包-25 BlueScreenView

BlueScreenView 今天来认识蓝屏 View 这应该是看 Windows 为啥会蓝屏的工具...

电子书阅读器上的浏览器 [Day10] 支援画面点击翻页

既然是电子书阅读器,一般人最常拿来用的功能应该就是看电子书吧。看电子书时如果要翻页的话,通常会点击画...

Day 01: 【序】– 架构与设计、代码、工程师

「你因为两个原因来读这本书:首先,你是位程序设计师。再者,你想成为一位更好的程序设计师」 取自: ...

[11] 建立进入页面和流程控制

这边你需要自己制作一个流程控制 不了解的话建可以画个图来确认现在在哪个流程 基本上都会回到主要操控介...

Day25|【Git】git stash 暂存档案

可能会遇到使用 git stash 指令情境: 假想今天可能在公司进行手中任务时,突然接收到老板或是...