iT邦幫忙

2023 iThome 鐵人賽

DAY 24
0

大綱

  1. 建立Layout頁面
  2. 首頁切版

前言

我們昨天開發出了導覽列,但我們接下來的頁面都會需要導覽列,最直覺的做法就是在每個Component裡面放進去Header.js

const HomePage = props =>{
    return(<div>
         <Header></Header>
         (...其他內容)
    </div>)
}
export default HomePage;
const PostList = props =>{
    return(<div>
         <Header></Header>
         (...其他內容)
    </div>)
}
export default PostList;

但這樣每次要使用Header的頁面就要加一次,若有多個頁面就要多次處理;且Header算是一個與當前component無直接關聯的元件(彼此不會進行資料傳遞),這樣擺放Header的方式會稍微讓人混淆它的用途。


那我們該如何處理?

1.建立Layout頁面

https://ithelp.ithome.com.tw/upload/images/20231009/20136558CCi0uioOj3.jpg

其實HeaderFooter是框架(網頁)內的固定內容,我們每次切換頁面(除了一些不需要它們的頁面)只要切換裡面的main content就好,所以我們要製作一個框架,將Header包起來,然後框架內要有個區塊(main content)能依照當前的頁面去切換。

pages資料夾底下建立Root.js

//Root.js

import Header from "../layout/Header";
import { Outlet } from 'react-router-dom';

const RootLayout = props =>{
    return <div className="overflow-x-hidden">
        <Header />
        <Outlet />
    </div>
}

export default RootLayout;

上面的<Outlet/>是透過父層路由元素來渲染其子路由元素,也就是我們用來渲染main content的地方。
它允許在渲染子路由時顯示嵌套的 UI(<Header/>)。如果父路由完全匹配,則將渲染子路由;如果沒有子路由,則不渲染任何內容。
Outlet說明


先建立今天要處理的首頁檔案,在pages資料夾底下建立HomePage.js

//HomePage.js
const HomePage = props =>{
    return  <div>HomePage</div>
}

export default HomePage;

https://ithelp.ithome.com.tw/upload/images/20231009/20136558Xgu5U172TL.jpg

接著回到App.js修改router設定

import './App.css';
import { createBrowserRouter, RouterProvider } from 'react-router-dom';
import { AuthProvider } from './contexts/AuthContext';
import Login  from './pages/Login';
import Register from './pages/Register';
import RootLayout  from './pages/Root'; //引入剛剛建立的RootLayout

const router = createBrowserRouter([
  {
    path: '/', 
    element: <RootLayout/>,
    children:[
     { path: '/', element: <HomePage />}
    ]
  },
  {
    path: '/login', 
    element: <Login/>
  },
  {
    path: '/register', 
    element: <Register/>
  }
]);

const App = () => {
  return (
    <AuthProvider>
      <RouterProvider router={router}/>
    </AuthProvider>
  );
}

export default App;

先設置RootLayout,接著設定它的子路由,並引入HomePage的component。

當我們切換到http://localhost:3000 時就能看到HomePage的內容
https://ithelp.ithome.com.tw/upload/images/20231009/201365581O3mF6q3Yu.jpg


2.首頁切版

Wireframe

https://ithelp.ithome.com.tw/upload/images/20231009/20136558TVECNBg45N.jpg

從上方的wireframe可以看到,最新文章下面的卡片是重複的樣式,所以可以把它抽成共用的樣式元件

建立HomeItem.js
components底下的UI資料夾建立HomeItem.js

//HomeItem.js
import postCover from '../../assets/computer.jpg';
import avatar from '../../assets/avatar.jpg';

const HomeItem = props =>{
   return <div className="mx-auto py-8 w-auto">
            <img src={postCover} alt="cover"/>
            <div className="flex items-center mt-2">
                <div className="text-left">
                    <h3 className="text-2xl font-semibold">What is Micro Frontend?</h3>
                    <p className="text-m text-gray-600">You may have heard from your backend team that </p>
                    <div className="flex items-center my-4">
                        <div className="w-[32px] h-[32px] rounded-full border border-gray-200 overflow-hidden">
                            <img src={avatar} alt="avatar"/>
                        </div>
                        <p className="text-violet-600 ml-2 text-sm">Jonas Kakaroto</p>
                        <p className="text-sm text-gray-400 ml-3 text-sm">Jan.10.2023</p>
                    </div>
                </div>
            </div>
        </div>
}

export default HomeItem;

回到我們剛剛已經建立好首頁的檔案HomePage.js,引入HomeItem,並處理其他的樣式。

//HomePage.js
import { Fragment } from 'react';
import HomeItem from '../components/Post/HomeItem';
import BlogCover from '../assets/blog-cover.jpg';

const HomePage = props =>{

    return <Fragment>
        <div className="w-screen pb-8 border-gray-200">
            <div className="py-10 mx-auto flex justify-center items-center">
                <h1 className="text-3xl font-bold">BLOG DEV</h1>
            </div>
            <div className="h-[50vh] overflow-hidden relative">
                <img src={BlogCover} alt="cover" className="sm:w-full sm:h-auto sm:max-w-full  max-w-none w-auto h-full"/>
                <h1 className="absolute top-1/2 left-1/2 -translate-y-1/2 -translate-x-1/2 text-5xl text-white font-bold tracking-wide">
                    <em>Stay Wired,Stay Inspired.</em>
                </h1>
            </div>
        </div>
        <div className="lg:w-[1024px] md:w-full md:px-8 px-6 mx-auto mt-12">
            <h2 className="text-violet-600 text-3xl font-semibold">Latest Posts</h2>
            <div className="grid gap-8 grid-cols-1 grid-rows-6 lg:grid-cols-3 lg:grid-rows-2 sm:grid-cols-2 md:grid-rows-3">
                <HomeItem />
                <HomeItem />
                <HomeItem />
                <HomeItem />
                <HomeItem />
                <HomeItem />
            </div>
        </div>
       
    </Fragment>
}

export default HomePage;

今天的程式碼在此

結語

/images/emoticon/emoticon16.gif
因為鐵人賽快來到結尾,所以會比較注重在功能處理,頁面樣式就會直接以程式碼帶過


上一篇
[Day23] 導覽列開發
下一篇
[Day25] 文章列表頁和標籤頁開發
系列文
初探全端之旅: 以MERN技術建立個人部落格31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言