theme: Chinese-red
前言
React介紹
React 是一個用於構建使用者介面的JavaScript庫,主要用於構建UI。React擁有較高的效能以及很多特點,比如JSX(這是JavaScript的擴充套件語法)和元件。元件化思想在React中的應用十分廣泛,通過構造元件可以將程式碼很好的得到複用。此外,React 的宣告式設計和通過對DOM的模擬,給它帶來了高效靈活的特點。
專案描述
小紅書作為一款定位於社交 && 電商 的App,近些年來越來越受到更多人的關注,它的使用者群體也在不斷擴大。作為一名小紅書的使用者,以及結合近期正在學習React 相關知識,便有了使用React 仿小紅書首頁的想法。此專案實現小紅書首頁的基本頁面,接下來就帶你進入專案展示及實戰。
成品展示
話不多說,直接上圖
搞錯了,重來
專案實戰
開始階段
在Vscode中建立一個React 專案,建立專案很多種方式,使用官方腳手架create-react-app或者Webpack建立,在此我使用的是Vitejs方式建立,這種方式會比其他方式快很多。如果大家對此感興趣的話,後面會寫一篇關於Vite和Webpack的文章,大家的點贊與支援,是我不斷創作的動力來源 ღ( ´・ᴗ・` )
資料夾配置
專案建立好後,接下來就是將相關檔案中的程式碼以及相關多餘的檔案清理乾淨,然後建立好專案中最基本的資料夾。
- api資料夾 用於網路請求方面
- assets資料夾 用於存放部分圖示圖片等靜態資源
- pages資料夾 用於頁面
- commpents資料夾 用於可複用的元件
更詳細的檔案目錄如下:
依賴安裝
相關資料夾配置完成後,可以開始安裝專案需要的依賴
- npm i axios 用於獲取後端資料
- npm i react-router react-router-dom 用於專案路由跳轉
- npm i styled-components 用於實現Css in JS
- npm i antd-mobile 一個好用的UI元件庫
- npm i classname 用於新增多個類名
安裝成功後如下所示:
元件及頁面分析
路由介紹
在以上工作完成後,接下來就是搭建相關路由了,路由在專案中是十分重要的。Route
【路由】可以理解為現實中路由器後面的介面,Routes
【路由器】可以理解為現實的路由器用來管理路由。在此專案中,我設定瞭如下幾個路由:
const Home = lazy(() => import('./pages/Home'))
const Mine = lazy(() => import('./pages/Mine'))
const Message = lazy(() => import('./pages/Message'))
const Shop = lazy(() => import('./pages/Shop'))
const Choose = lazy(() => import('./pages/Choose'))
<Routes>
<Route path="/" element={<Home/>}></Route>
<Route path="/home" element={<Home/>}></Route>
<Route path="/mine" element={<Mine/>}></Route>
<Route path="/message" element={<Message/>}></Route>
<Route path="/shop" element={<Shop/>}></Route>
<Route path='/choose' element={<Choose />}></Route>
</Routes>
路由搭建需要注意以下幾點:
- 在main.jsx 中引入{BrowserRouter}
方能正常使用
- 使用路由懶載入,可提升載入速度,需引入{Suspense}
若出現某個頁面跳轉後不顯示底部導航欄,可以通過簡單的條件判斷和{useLocation}
接受傳來的值來實現。比如如下所示:
import {useLocation} from 'react-router-dom'
const {pathname}=useLocation()
if (pathname == '/choose') return
資料請求
在此專案中採用的是fastmock來請求與管理資料,然後在api資料夾中建立request.js來獲取資料。後續在相關頁面中引入即可。
```
import axios from 'axios'
export const Getlist = () =>
axios.get
('https://www.fastmock.site/mock/33e7fec4e60b54344eaa2c59a55b379d/red_book/red_book/list')
export const Getfood = () =>
axios.get
('https://www.fastmock.site/mock/33e7fec4e60b54344eaa2c59a55b379d/red_book/red_book/food')
```
底部導航欄
底部導航欄通過路由的切換來實現。上面已經講過一些路由知識,在此就不做過多描述。在components資料夾中建立Footer元件,用於底部導航欄。在此注意點選中間加號跳轉後底部導航欄不會一起跳轉,因此需要做相關判斷來實現跳轉新頁面,原始碼如下:
Footer.jsx
```
import React from 'react'
import {Link,useLocation} from 'react-router-dom'
import {FooterWrapper} from './style'
import classnames from 'classnames'
import { Badge } from 'antd-mobile'
function Footer(props) {
const {pathname}=useLocation()
if (pathname == '/choose') return
return (
首頁
商城
訊息
我
)
}
export default Footer
```
主頁面引入Footer,部分原始碼如下:
```
<>
}>
}>
}>
}>
}>
}>
```
頂部導航欄
頂部導航欄通過Tab欄來實現內容的切換。此處有兩處導航欄,在發現頁面下也有一處導航欄,因此需要實現兩次導航欄效果。兩次導航欄實現十分簡單,原始碼如下:
Home .jsx
```
import React, { useState,useEffect } from "react";
import { Tabs,Popup } from 'antd-mobile'
import Care from './Care'
import Find from './Find'
import City from './City'
import Search from '../Search'
import Daily from '../Daily'
import './style.css'
const Home = () =>{
const [visible1, setVisible1] = useState(false)
const [visible2, setVisible2] = useState(false)
return(
<span
onClick={() => {
setVisible1(true)
}}
>
<i className="iconfont icon-yuzhouxingqiu-12"></i>
</span>
<Popup
visible={visible1}
onMaskClick={() => {
setVisible1(false)
}}
position='left'
bodyStyle={{ height: '100%',width:'100%' }}
>
{<Daily />}
</Popup>
<span
onClick={() => {
setVisible2(true)
}}
>
<i className="iconfont icon-sousuo"></i>
</span>
<Popup
visible={visible2}
onMaskClick={() => {
setVisible2(false)
}}
position='right'
bodyStyle={{ height: '100%',width:'100%' }}
>
{<Search />}
</Popup>
</div>
)
}
export default Home
```
Find.jsx
```
import React, { useState,useEffect } from "react";
import { Tabs,Collapse,SpinLoading } from 'antd-mobile'
import Recommend from '../../Recommend'
import Video from '../../Video'
import Liver from '../../Liver'
import Food from '../../Food'
import { Getlist } from '../../../api/request'
import { Getfood } from "../../../api/request"
import './style.css'
const Find = () =>{
const [list,SetList] = useState([])
useEffect(()=>{
(async() => {
let { data } = await Getlist()
SetList(data)
})()
},[])
const [food,SetFood] = useState([])
useEffect(()=>{
(async() => {
let { data } = await Getfood()
SetFood(data)
})()
},[])
return(
<div>
<Tabs defaultActiveKey='1' style={
{'--title-font-size':'15px','--active-line-height':'0px',
'--active-title-color':'#ed2b43'}}>
<Tabs.Tab title='推薦' key='1'>
{list.map(item=>(
<Recommend source={item} key={item.id}/>
))
}
</Tabs.Tab>
<Tabs.Tab title='視訊' key='2'>
<Video/>
</Tabs.Tab>
<Tabs.Tab title='直播' key='3'>
<Liver />
</Tabs.Tab>
<Tabs.Tab title='美食' key='4'>
{food.map(item=>(
<Food entry={item} key={item.id}/>
))
}
</Tabs.Tab>
<Tabs.Tab title='知識科普' key='5'>
.........
</Tabs.Tab>
.........
此後程式碼大致相同,便在此處省略
</Tabs>
<SpinLoading style={{'--color':'#ed2b43'}} className="load"/>
</div>
)
}
export default Find
```
本專案中Tab欄使用的是antd-mobile裡封裝好的Tab欄,參考antd-mobile裡的文件,然後引入相關元件,即可使用。雖然用起來比較方便,但是因為是已經封裝好的元件,對於一些樣式的修改會比較侷限。若要修改樣式,可以參考文件對其相關樣式進行修改或者加入className類名重新定義相關樣式。
下面附上相關網址,感興趣的朋友可以參考相關文件,這是一個不錯的UI元件庫。
Ant Design Mobile - Ant Design Mobile
首頁內容
首頁是此專案的主頁面,進入此頁面後,可以實現頁面跳轉等相關功能,頁面上的資料儲存在fastmock中。然後在Recommend和Food頁面中通過遍歷將所需資料獲取在頁面上。此外,跳轉到搜尋頁面,裡面採用的搜尋框也是antd-mobile裡封裝好的Search,對樣式稍作修改然後直接呼叫即可。對於圖示,採用iconfont上的圖示足以滿足大部分需求。在assets資料夾中引入提前加入好圖示的font資料夾,此後也能方便地在font資料夾中修改圖示樣式。部分原始碼如下:
Search.jsx
```
import React from "react";
import { NavBar,SearchBar } from "antd-mobile";
import {Link} from "react-router-dom"
import './style.css'
const Search = () =>{
return(
}}
/>
搜尋
)
}
export default Search
```
Recommend.jsx
```
import React from "react";
import './style.css'
const Recommend = ({source}) =>{
const {img,content,author,icon} = source
return(
{content}
{author}
)
}
export default Recommend
```
Food.jsx
```
import React from "react";
import './style.css'
const Food = ({entry}) =>{
const {img,content,author,icon} = entry
return(
{content}
{author}
)
}
export default Food
```
總結
這是初步搭建的專案,裡面有許多功能以及相關元件還未完全實現,後期隨著對React 知識的深入學習與掌握,會將此專案加以修改和完善,並繼續以此發文。如有優化或者錯誤的地方,歡迎各位大佬在評論區裡指出。最後,如果此篇文章能給大家帶來幫助的話,謝謝各位的點贊 ღ( ´・ᴗ・` )