iThome
鐵人賽
30天
今天要處理的是讓每個頁面都有自己的Container來包裝排版,畢竟每個頁面的排版不一定都相同,這個專案主要就兩個頁面,首頁及標記編輯頁面,兩個預想的排版差異滿大的,所以就選擇分開裝囉!
那就先來做首頁的Container吧!
先在/src/components
裡新增main
資料夾,這個資料夾我打算把主要畫面呈現的component集中放置在內。再來在main
內新增HomePage.jsx
。
之後就是開始調版面時間啦,就大概調到自己覺得看得下去的地步,當然對自己有美觀的要求就加油吧,我先放棄XD,大概調個間距就好~
這是我最終調整完的版本:HomePage.jsx
:
import React, { useState, useEffect } from 'react'
import { Box } from '@mui/material'
import VideoCard from '../VideoCard'
export default function HomePage() {
return (
<Box sx={{ p: 3, display: "flex", flexWrap: "wrap", justifyContent: "center" }}>
<VideoCard
v={"Ga22mpTDS6A"}
title={"東京版《Joe是要對決》日幣30000元的奢華壽喜燒對決日幣600元的平價壽喜燒!Ep127@徐海莉 Hailey@流川莉蘿 Rilo ch."}
/>
<VideoCard
v={"SxQgIJ3rQ3c"}
title={"NEAL對決秋天的王者李宰赫!Royal Roader再度誕生!個人賽決賽SET 2《2022 跑跑卡丁車聯賽 S2》"}
/>
</Box>
)
}
VideoCard.jsx
:
import React from 'react'
import { Card, CardMedia, CardContent, Typography } from '@mui/material'
import { Link } from 'react-router-dom' // 導入Link
export default function VideoCard(props) {
const { v, title } = props
return (
<Card sx={{ maxWidth: 480, m: 1 }}>
<Link className='reset' to={`/watch?v=${v}`}>
<CardMedia
component="img"
// height="360"
image={`https://img.youtube.com/vi/${v}/hqdefault.jpg`}
alt="green iguana"
/>
<CardContent>
<Typography gutterBottom variant="h5" component="div" className='twoline'>
{title}
</Typography>
</CardContent>
</Link>
</Card>
)
}
新增的CSS (為了把Link
產生的超連結變色和hover拿掉):
.reset{
text-decoration: none;
color: #000;
outline: none;
}
先看看上面的HomePage.jsx
,可以發現目前卡片還都是寫死的情況,接下來會模擬API已經取得資料後,當作參數傳進去的方式去用mapping讓卡片渲染出來。
因為要取得資料的時間點會是在訪問HomePage的時候,所以把模擬的data放在HomePage中:
import React, { useState, useEffect } from 'react'
import { Box } from '@mui/material'
import VideoCard from '../VideoCard'
export default function HomePage() {
const [data, setData] = useState(null)
useEffect(() => {
// 第一次進入HomePage.jsx時去取得資料
getData()
}, [])
const getData = () => {
// 模擬API取得資料
setData(
[
{ v: "Ga22mpTDS6A", title: "東京版《Joe是要對決》日幣30000元的奢華壽喜燒對決日幣600元的平價壽喜燒!Ep127@徐海莉 Hailey@流川莉蘿 Rilo ch." },
{ v: "SxQgIJ3rQ3c", title: "NEAL對決秋天的王者李宰赫!Royal Roader再度誕生!個人賽決賽SET 2《2022 跑跑卡丁車聯賽 S2》" }
]
)
}
return (
<Box sx={{ p: 3, display: "flex", flexWrap: "wrap", justifyContent: "center" }}>
{/** 用.map的方式把array的資料一個一個渲染出來 */}
{!!data && data.map(d =>
<VideoCard
// key用來幫助React分辨哪些項目被改變、增加或刪除
key={d.v}
v={d.v}
title={d.title}
/>
)}
</Box>
)
}
在mapping中有個重點,就是如果是mapping component的話要記得在component裡加入key參數,並給予一個在這個陣列裡不會重複出現的值。
當然如果裡面的元素不會變動的話有個偷懶的方法,但是不建議使用:
{!!data && data.map((d, index) =>
<VideoCard
key={index}
v={d.v}
title={d.title}
/>
)}
偷懶的方法藏在map的第二個參數裡,index代表是array的第幾個值 (從0開始),所以一定是唯一的,但並不推薦使用在會改變順序的情況,可能會發生意想不到的錯誤。
可以發現array的資料成功變出來了。
當然我們也可以模擬資料很多的情況,看看會變甚麼樣子吧!
整理完後版面是不是看起來清爽很多了呢?再來就是處理編輯頁面啦~不過居然剩下10天了,時間過得好快,開始擔心結束的時候還沒講完了...?
附上專案:2022-iThomeIronman
對資安或Mapbox有興趣的話也可以觀看我們團隊的鐵人發文喔~