実践的な指導:エントリーレベルのReact模倣小紅書ホームページ

image.png

序文

Reactの紹介

  Reactは、主にUIを構築するためのユーザーインターフェイスを構築するためのJavaScriptライブラリです。Reactは、JSX(JavaScriptの拡張機能)やコンポーネントなどの高性能と機能を備えています。コンポーネント化のアイデアはReactで広く使用されており、コンポーネントを構築することでコードを適切に再利用できます。さらに、Reactの宣言型設計とDOMのエミュレーションにより、Reactは効率的かつ柔軟になります。

プロジェクトの説明

ソーシャル&&eコマースに  位置するアプリとして、小紅書は近年ますます注目を集めており、そのユーザーベースも拡大しています。Xiaohongshuのユーザーとして、 Reactの最近の知識と組み合わせて、Reactを使用してXiaohongshuのホームページを模倣することを考えています。このプロジェクトは、小紅書のホームページの基本ページを実現し、プロジェクトの展示と実際の戦闘に移動します。

完成品展示

こちらが画像です

image.png


間違えた、戻ってきて

QQ画面記録20220705164119.gif


プロジェクト戦闘

初期

  VscodeでReactプロジェクトを作成します。プロジェクトを作成する方法はたくさんあります。公式のscaffoldcreate-react-appまたはWebpackを使用して作成します。ここでは、Vitejsメソッドを使用して作成します。これは、他のメソッドよりもはるかに高速です。これに興味があれば、後でViteとWebpackについての記事を書きます。あなたのいいねとサポートが私の継続的な創造の源ですღ(´・ᴗ・ `)

フォルダ構成

  プロジェクトが作成されたら、次のステップは、関連ファイルと関連冗長ファイルのコードをクリーンアップしてから、プロジェクトに最も基本的なフォルダーを作成することです。

  • ネットワークリクエスト用のAPIフォルダ
  • アセットフォルダは、アイコンや画像などの静的リソースを保存するために使用されます
  • ページのページフォルダ
  • 再利用可能なコンポーネントのcommpentsフォルダー

  より詳細なファイルディレクトリは次のとおりです。

image.png

依存関係のインストール

  相关文件夹配置完成后,可以开始安装项目需要的依赖

  • 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   用于添加多个类名

  安装成功后如下所示:

image.png

组件及页面分析

路由介绍

  在以上工作完成后,接下来就是搭建相关路由了,路由在项目中是十分重要的。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}

image.png

  • 若出现某个页面跳转后不显示底部导航栏,可以通过简单的条件判断和{useLocation}接受传来的值来实现。比如如下所示:
import {useLocation} from 'react-router-dom'

const {pathname}=useLocation()
if (pathname == '/choose') return

数据请求

  在此项目中采用的是fastmock来请求与管理数据,然后在api文件夹中创建request.js来获取数据。后续在相关页面中引入即可。

image.png

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')

底部导航栏

QQ录屏20220705171130.gif


  底部导航栏通过路由的切换来实现。上面已经讲过一些路由知识,在此就不做过多描述。在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 />
</>

顶部导航栏

QQ录屏20220705171330.gif


  上部のナビゲーションバーは、タブバーを使用してコンテンツを切り替えます。ここには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

ホームコンテンツ

QQ录屏20220705164119.gif


  ホームページはこのプロジェクトのメインページです。このページに入ると、ページジャンプなどの関連機能を実現できます。ページ上のデータは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の知識の詳細な調査と習得により、このプロジェクトは変更および改善され、引き続き公開されます。最適化や間違いがある場合は、コメント領域でそれらを指摘してください。最後に、この記事があなたを助けることができるなら、あなたの好きなものをありがとうღ(´・ᴗ・ `)

おすすめ

転載: juejin.im/post/7116817540055040013