手摸手教你:入门级React仿小红书首页

语言: CN / TW / HK

theme: Chinese-red

image.png

前言

React介绍

  React是一个用于构建用户界面的JavaScript库,主要用于构建UI。React拥有较高的性能以及很多特点,比如JSX(这是JavaScript的扩展语法)和组件。组件化思想在React中的应用十分广泛,通过构造组件可以将代码很好的得到复用。此外,React的声明式设计和通过对DOM的模拟,给它带来了高效灵活的特点。

项目描述

  小红书作为一款定位于社交 && 电商 的App,近些年来越来越受到更多人的关注,它的用户群体也在不断扩大。作为一名小红书的使用者,以及结合近期正在学习React相关知识,便有了使用React仿小红书首页的想法。此项目实现小红书首页的基本页面,接下来就带你进入项目展示及实战。

成品展示

话不多说,直接上图

image.png


搞错了,重来

QQ录屏20220705164119.gif


项目实战

开始阶段

  在Vscode中创建一个React项目,创建项目很多种方式,使用官方脚手架create-react-app或者Webpack创建,在此我使用的是Vitejs方式创建,这种方式会比其他方式快很多。如果大家对此感兴趣的话,后面会写一篇关于Vite和Webpack的文章,大家的点赞与支持,是我不断创作的动力来源 ღ( ´・ᴗ・` )

文件夹配置

  项目创建好后,接下来就是将相关文件中的代码以及相关多余的文件清理干净,然后创建好项目中最基本的文件夹。 - api文件夹  用于网络请求方面 - assets文件夹  用于存放部分图标图片等静态资源 - pages文件夹  用于页面 - 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 ('http://www.fastmock.site/mock/33e7fec4e60b54344eaa2c59a55b379d/red_book/red_book/list') export const Getfood = () =>
axios.get ('http://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 ( 首页 商城 消息 ) }

export default Footer ```


  主页面引入Footer,部分源码如下: ``` <> }> }> }> }> }> }>

```

顶部导航栏

QQ录屏20220705171330.gif


  顶部导航栏通过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

首页内容

QQ录屏20220705164119.gif


  首页是此项目的主页面,进入此页面后,可以实现页面跳转等相关功能,页面上的数据存储在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知识的深入学习与掌握,会将此项目加以修改和完善,并继续以此发文。如有优化或者错误的地方,欢迎各位大佬在评论区里指出。最后,如果此篇文章能给大家带来帮助的话,谢谢各位的点赞 ღ( ´・ᴗ・` )