React开发第一个组件-仿小红书商品展示组件

991 阅读4分钟

React开发第一个组件-仿小红书商品展示组件

image.png 持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第1天,点击查看活动详情

简介

React作为进击大厂必学的框架技术,传统的代码思想需要手动修改DOM对象,对浏览器的性能产生巨大的问题。框架就能很好的解决一些问题。以声明式编程和组件化开发为理念框架尤为重要。接下来我们以组件化开发思想来通过实战小红书商品展示功能,介绍我的思路以及方法,希望对前端朋友们的react学习有帮助。

  • [技术使用方面]
    • 前端三剑客Html.css.javascript
    • React Hooks全家桶
    • ant design-mobile 非常好用的框架
    • styled-components 样式设计
    • axios+fastmock 数据请求方式

正文

我们先来看看组件实现后的效果吧:

a.gif

  1. 组件设计思路
  • 头部搜索组件:静态组件的实现,后面扩展购物车组件实现
  • 底部路由导航组件:通过路由的跳转实现单页面的切换效果
  • 轮播图组件:使用swiper包,实现轮播效果
  • 分类选择组件:静态组件的实现
  • 商品展示组件:在父组件的请求数据,通过props传递数据给子组件
  • 商品详情组件:点击不同的商品组件,在详情页面展示不同的数据 接下来看整个项目的目录结构

image.png

  1. 路由的实现效果 点击导航栏选择不同的页面展示,共为五个导航模块

image.png

配置路由跳转组件,通过对<Link/>一个路径,在<Route/>匹配路径,选择不同的组件进行跳转。

import { useState } from 'react'
import logo from './logo.svg'
import './App.css'
import {Routes,Route,Router,useParams} from 'react-router-dom'
import Footer from './components/Footer'
import Home from './pages/Home'
import Shop from './pages/Shop'
import Add from './pages/Add'
import Mine from './pages/Mine'
import Order from './pages/Order'
import Follow from './pages/Home/Follow'
import Find from './pages/Home/Find'
import Native from './pages/Home/Native'
import Detail from './components/Detail' 



function App() {

  return (
    <div className="App">
      <Routes>
          <Route path='/' element={<Home/>} />
          <Route path='/home' element={<Home/>} >
            <Route path='/home/follow' element={<Follow/>}/>
            <Route path='/home/find' element={<Find/>}/>
            <Route path='/home/native' element={<Native/>}/>
          </Route>
          <Route path='/shop' element={<Shop/>} />
          <Route path='/add' element={<Add/>} />
          <Route path='/mine' element={<Mine/>} />
          <Route path='/order' element={<Order/>} />   
          <Route path='/detail' element={<Detail/>}/>
      </Routes>
      <Footer/>
    </div>
  )
}

export default App

底部导航,点击不同选项,样式添加

<Link to="/home" className={classnames({active:pathname == '/home' || pathname == '/' })}>
                <i className="fa fa-home"></i>
                <span>首页</span>
            </Link>
            <Link to="/shop" className={classnames({active:pathname == '/shop'})}>
                <i className="fa fa-shopping-bag"></i>
                <span>购物</span>
            </Link>

            <Link to="/add" className={classnames({add:true})}>
                <i className="fa fa-plus-square-o fa-3x"></i>
                
            </Link>
            <Link to="/order" className={classnames({active:pathname == '/order'})}>
                <i className="fa fa-book"></i>
                <span>消息</span>
            </Link>
            <Link to="/mine"  className={classnames({active:pathname == '/mine'})}>
                <i className="fa fa-user"></i>
                <span></span>
            </Link>

这里在添加一个动态样式,下载classnames这个包,可以方便的添加多个样式,给需要改变样式一个boolean值,在通过获取当前页面路径第一个/后面的路径,比较相等的就添加样式,实现动态切换样式效果。

  1. 轮播组件实现 通过使用swiper包的使用,实现轮播效果, 在父组件请求数据通过props传递给子组件数据进行展示。

a.gif 实例一个swiper对象

useEffect(()=>{
        new Swiper('.btn-banners',{
            loop:true,
           autoplay:{
            delay:1000
           }
        })
    })

数据遍历展示实现轮播效果

 <div className="btn-banners swiper-container">
            <div className="swiper-wrapper">
                {
                      shop.map(item=>(
                         <div className="swiper-slide">
                           <img src={item.images} alt="" /> </div>
                      ))
               
                }
              
                
            </div>
        </div>

4.商品分类选择组件

写好组件的样式框架,在父组件获取数据,传递给子组件,进行数据展示

image.png

<div className="banners-slide">
                   {
                    banners.map(item=>(
                      <Link to='#' className='banners-item'>
                        <div>
                          <p>
                            <img src={item.iomages} alt="" />
                          </p>
                          <span>
                            {item.title}
                          </span>
                        </div>
                      </Link>
                    ))
                   }
        </div>
                
  1. 商品展示组件 作为一个功能组件,同样在父组件请求数据实现遍历渲染,再点击跳转到自己对应的商品详情页,传递自己的id找到对应的商品详情页。

image.png

<div className='shopinfo'>
        {
            shopinfo.map(item=>(
                <Link
                to={
                    {
                        pathname:'/detail',
                        search:`id=${item.id}`
                    }
                }
                key={item.id}
                style={{display:'block'}}
                >
                             <div className='shopinfo-box'>     
             <div>
        <span>
            <img src={item.images}alt="" />
        </span>
      </div>
      <p>{item.title}</p>
      <h3>{item.price}</h3>
        </div>
                </Link>
         
               
             
            ))
        }
     
     
    </div>

在这个组件通过<Link/>实现路由的跳转,给路由传参,传一个Id找到对应的自己的数据,在详情页面进行展示。

  1. 商品详情页面组件 在详情页面展示点击过来商品的详细信息,通过路由传递过来的id参数,再对请求过来的数据进行过滤,过滤出id相同的数据在页面展示

点击第一个商品展示:

image.png

点击第二个商品展示:

image.png 通过对请求的数据进行过滤出来对应数据

const [search] = useSearchParams()
    const detailid= search.get('id') || ''

useEffect(()=>{
    let detaildataa= detail.filter((item)=>
    detailid ==   item.id
     )
     setDetaill(detaildataa)
},[detail])

通过请求过来的数据进行页面展示

<div className="btn-a btn-banners swiper-container">
            <div className="swiper-wrapper">
                {
                    
                    detaill.length !==0 ?    detaill[0].img.map((item)=>(
                        <div className="swiper-slide">
                           <img src={item} alt="" className='aimg'/>
                           </div>
                     )):''
                    
                    
                }                                                               
            </div>
        </div>
        <div className="detail-body">
            <div className='s-a'>
                 <span>¥
                <i>{detaill.length !==0 ? detaill[0].price:'' }</i>
            </span>
            <i className='fa fa-star-o'></i>
            </div>
            <div className='title'>
{detaill.length !==0 ? detaill[0].title:'' }
            </div>

在页面展示处理的小细节,当请求数据时,刚开始给一个默认值,会使页面展示报错,因此添加一个判断功能,判断数组长度不为空时进行展示数据。以及在头部返回按钮,直接给按钮一个<Link to='/shop'/>跳转到商品展示页

最后

以上就是组件完成的全部内容了,在一些细节处理方面还有不足之处,尤其在页面的一些样式 ,后续还将持续更新。在一些功能方面,比如收藏,加入购物车,购买等功能的实现,后面尽快完善起来.