序文
Reactの紹介
Reactは、主にUIを構築するためのユーザーインターフェイスを構築するためのJavaScriptライブラリです。Reactは、JSX(JavaScriptの拡張機能)やコンポーネントなどの高性能と機能を備えています。コンポーネント化のアイデアはReactで広く使用されており、コンポーネントを構築することでコードを適切に再利用できます。さらに、Reactの宣言型設計とDOMのエミュレーションにより、Reactは効率的かつ柔軟になります。
プロジェクトの説明
ソーシャル&&eコマースに 位置するアプリとして、小紅書は近年ますます注目を集めており、そのユーザーベースも拡大しています。Xiaohongshuのユーザーとして、 Reactの最近の知識と組み合わせて、Reactを使用してXiaohongshuのホームページを模倣することを考えています。このプロジェクトは、小紅書のホームページの基本ページを実現し、プロジェクトの展示と実際の戦闘に移動します。
完成品展示
こちらが画像です
間違えた、戻ってきて
プロジェクト戦闘
初期
VscodeでReactプロジェクトを作成します。プロジェクトを作成する方法はたくさんあります。公式のscaffoldcreate-react-appまたはWebpackを使用して作成します。ここでは、Vitejsメソッドを使用して作成します。これは、他のメソッドよりもはるかに高速です。これに興味があれば、後でViteとWebpackについての記事を書きます。あなたのいいねとサポートが私の継続的な創造の源ですღ(´・ᴗ・ `)
フォルダ構成
プロジェクトが作成されたら、次のステップは、関連ファイルと関連冗長ファイルのコードをクリーンアップしてから、プロジェクトに最も基本的なフォルダーを作成することです。
- ネットワークリクエスト用のAPIフォルダ
- アセットフォルダは、アイコンや画像などの静的リソースを保存するために使用されます
- ページのページフォルダ
- 再利用可能なコンポーネントの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 (
<FooterWrapper>
<Link to="/" className={classnames({active:pathname == '/'})}>
<span>首页</span>
</Link>
<Link to="/shop" className={classnames({active:pathname == '/shop'})}>
<span>商城</span>
</Link>
<Link to="/choose" className={classnames({active:pathname == '/choose'})}>
<span><i className="iconfont icon-Addtianjia3"></i></span>
</Link>
<Link to="/message" className={classnames({active:pathname == '/message'})}>
<Badge content='5'><span>消息</span></Badge>
</Link>
<Link to="/mine" className={classnames({active:pathname == '/mine'})}>
<span>我</span></Link>
</FooterWrapper>
)
}
export default Footer
主页面引入Footer,部分源码如下:
<>
<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>
<Footer />
</>
顶部导航栏
上部のナビゲーションバーは、タブバーを使用してコンテンツを切り替えます。ここには2つのナビゲーションバーがあり、検出ページの下にもナビゲーションバーがあるため、ナビゲーションバー効果を2回実装する必要があります。2つのナビゲーションバーの実装は非常に簡単です。ソースコードは次のとおりです
。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(
<div>
<Tabs defaultActiveKey='find' style={
{'--active-line-color':'#ed2b43','--active-title-color':'#000000'}}>
<Tabs.Tab title='关注' key='care'>
<Care/>
</Tabs.Tab>
<Tabs.Tab title='发现' key='find'>
<Find/>
</Tabs.Tab>
<Tabs.Tab title='城市' key='city'>
<City/>
</Tabs.Tab>
</Tabs>
<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
このプロジェクトのタブバーは、antd-mobileにパッケージ化されたタブバーを使用し、antd-mobileのドキュメントを参照してから、関連するコンポーネントを紹介すると、それを使用できます。パッケージ化されたコンポーネントであるため、使用する方が便利ですが、一部のスタイルの変更はより制限されます。スタイルを変更するには、ドキュメントを参照して関連するスタイルを変更するか、classNameクラス名を追加して関連するスタイルを再定義します。関連するウェブサイトを以下に添付します。興味のある友人は関連するドキュメントを参照できます。これは優れたUIコンポーネントライブラリです。
Ant Design Mobile-Ant Design Mobile
ホームコンテンツ
ホームページはこのプロジェクトのメインページです。このページに入ると、ページジャンプなどの関連機能を実現できます。ページ上のデータはfastmockに保存されます。次に、RecommendページとFoodページで、必要なデータがページをトラバースすることで取得されます。さらに、検索ページにジャンプすると、そこで使用されている検索ボックスもantd-mobileにパッケージ化された検索です。スタイルを少し変更してから直接呼び出すことができます。アイコンの場合、ほとんどのニーズにはiconfontのアイコンを使用するだけで十分です。アセットフォルダに事前にアイコンを追加したフォントフォルダを導入すると、フォントフォルダのアイコンスタイルを簡単に変更できます。ソースコードの一部は次のとおりです。
Search.jsx
import React from "react";
import { NavBar,SearchBar } from "antd-mobile";
import {Link} from "react-router-dom"
import './style.css'
const Search = () =>{
return(
<div>
<Link to='/shop'>
<NavBar>
<SearchBar
className="searchbar"
placeholder='请输入内容'
style={{
'--border-radius': '100px',
'--background': '#f5f5f5',
'--height': '30px',
'--placeholder-color':'#afafaf',
}}
/>
<span className="search">搜索</span>
</NavBar>
</Link>
</div>
)
}
export default Search
Recommendation.jsx
import React from "react";
import './style.css'
const Recommend = ({source}) =>{
const {img,content,author,icon} = source
return(
<div className="List">
<img src={img} className="list-img" />
<div className="list-content">{content}</div>
<div className="list-author">
<img src={icon} className="icon-img"></img>
<div className="list-h">{author}</div>
<i className="iconfont icon-dianzan"></i>
</div>
</div>
)
}
export default Recommend
Food.jsx
import React from "react";
import './style.css'
const Food = ({entry}) =>{
const {img,content,author,icon} = entry
return(
<div className="List">
<img src={img} className="list-img" />
<div className="list-content">{content}</div>
<div className="list-author">
<img src={icon} className="icon-img"></img>
<div className="list-h">{author}</div>
<i className="iconfont icon-dianzan"></i>
</div>
</div>
)
}
export default Food
要約する
これは予備的なプロジェクトであり、十分に実現されていない多くの機能と関連コンポーネントがあります。その後、Reactの知識の詳細な調査と習得により、このプロジェクトは変更および改善され、引き続き公開されます。最適化や間違いがある場合は、コメント領域でそれらを指摘してください。最後に、この記事があなたを助けることができるなら、あなたの好きなものをありがとうღ(´・ᴗ・ `)