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 知識的深入學習與掌握,會將此項目加以修改和完善,並繼續以此發文。如有優化或者錯誤的地方,歡迎各位大佬在評論區裏指出。最後,如果此篇文章能給大家帶來幫助的話,謝謝各位的點贊 ღ( ´・ᴗ・` )