likes
comments
collection
share

React入门实战——腾讯掌上道聚城主页组件开发

作者站长头像
站长
· 阅读数 51

前言

React作为前端使用频率最高的三大框架之一,组件化是其核心思想。对于学习过React的前端小伙伴来说,React中一切都是组件(相信大家都耳熟能详)。下面将介绍本人实战项目中对复杂组件的组件化设计的过程,希望对各位小伙伴有一定的帮助和启发。

前期准备

在项目开始之前,我们需要对项目所需的开源软件库和相关UI组件有一定的了解。下面是本人在开发中用到的开源库(不太了解的小伙伴可以查阅相关文档进行学习)。

  • antd-mobile 是一个基于Preact/React/React Native的UI组件库,拥有大量实用易上手的组件。
  • Swiper 能实现触屏焦点图、触屏Tab切换、触屏轮播图切换等常用效果。
  • axios 是一个基于 promise 的网络请求库,用于获取后端数据,是前端常用的数据请求工具。
  • font-awesome 一套绝佳的图标字体库和CSS框架。
  • classnames 很方便地实现给元素添加多个类名。
  • styled-components 是css-in-js 最热门的一个库,可以为您的样式生成唯一的类名,并能完成css样式书写的嵌套功能。

另外,开发过程中还用到在线接口工具 faskmock,它可以让你在没有后端程序的情况下能真实地在线模拟ajax请求。

项目实现

项目效果图

React入门实战——腾讯掌上道聚城主页组件开发

<LOLHome/>英雄联盟主页组件

React入门实战——腾讯掌上道聚城主页组件开发

1. 设计思路

掌上道聚城主页的实现,需采用组件化思想,细化主页为以下组件。

  • <Header/> 头部组件

  • <Home/> 精选主页组件(此组件还需细分为其他功能子组件)

    • <Banners/> 轮播图组件

    • <ActivitiesInfo/> 活动功能栏组件

    • <Activities /> 活动栏组件

    • <GameInfo/> 资讯栏组件

    • <SaleInfo/> 特惠区组件

  • <Footer/> 底部组件

另外,英雄联盟专区首页也需如<Home/>组件一样细分功能模块,具体的就不再赘述。

根据需求,细分功能完成项目架构,项目目录如下:

React入门实战——腾讯掌上道聚城主页组件开发

2 实现Header组件

头部组件通过 Link 路由切换实现页面的跳转,并且完成tab转换。使用useLocation() 我们解构出 pathname,用来判断当前路径是否匹配,如果匹配将通过classnames将active 样式添加上去,使tab拥有蓝色下划线效果。

import React from "react";
import { HeaderWrapper } from "./style";
import { Link, useLocation } from "react-router-dom";
import classnames from "classnames";

export default function Header() {
  const { pathname } = useLocation();
  return (
    <HeaderWrapper>
      <div className="nav-box">
        <i className="iconfont icon-saoyisao"></i>
        <Link
          to="/"
          className={classnames(
            { navitem: true },
            { active: pathname == "/home" || pathname == "/" }
          )}
        >
          精选
        </Link>
        <Link
          to="/lol"
          className={classnames(
            { navitem: true },
            { active: pathname == "/lol" }
          )}
        >
          英雄联盟
        </Link>
        <Link
          to="/cf"
          className={classnames(
            { navitem: true },
            { active: pathname == "/cf" }
          )}
        >
          CF穿越火线
        </Link>
        <Link to="/gamelist">
          <i className="iconfont icon-jiahao icon-right"></i>
        </Link>
      </div>
    </HeaderWrapper>
  );
}

效果图如下:

React入门实战——腾讯掌上道聚城主页组件开发

3. 实现Home 主页组件

<Home/> 精选主页组件细分为以下5个功能组件

  • <Banners/> 轮播图组件
  • <ActivitiesInfo/> 活动功能栏组件
  • <Activities /> 活动栏组件
  • <GameInfo/> 资讯栏组件
  • <SaleInfo/> 特惠区组件

3.1 <Banners/> 轮播图组件

轮播图我是使用的4.5.0版本的Swiper,轮播图的具体实现有固定的的html结构(小伙伴们可通过前文中的链接进行学习),此处需注意Swiper4轮播设置 autoplay: true后,即默认设置了 disableOnInteraction: true,这将导致用户手动切换swiper之后,轮播图不再自动切换。需要将 autoplay: true 换成 autoplay:{disableOnInteraction: false} ,设置后用户操作swiper之后自动切换不会停止,每次都会重新启动autoplay

import React, { useEffect } from "react";
import { Wrapper } from "./style";
import { Link } from "react-router-dom";
import Swiper from "swiper";

export default function Banners() {
  useEffect(() => {
    new Swiper(".btn-banners", {
      loop: true,
      // autoplay: true,
      autoplay: { disableOnInteraction: false },
      pagination: {
        el: ".swiper-pagination",
      },
    });
  }, []);

  return (
    <Wrapper>
      <div className="btn-banners swiper-container">
        <div className="swiper-wrapper">
          <div className="swiper-slide">
            <Link to="/lol">
              <img 
                src="https://game.gtimg.cn/images/daojushop/uploads/ad/202206/20220624113503_254960.jpg"
                alt=""
              />
            </Link>
          </div>
          <div className="swiper-slide">
            <Link to="/lol">
              <img
                src="https://game.gtimg.cn/images/daojushop/uploads/ad/202206/20220610102334_849392.jpg"
                alt=""
              />
            </Link>
          </div>
          <div className="swiper-slide">
            <Link to="/lol">
              <img
                src="https://game.gtimg.cn/images/daojushop/uploads/ad/202206/20220610110952_781001.jpg"
                alt=""
              />
            </Link>
          </div>
          <div className="swiper-slide">
            <Link to="/lol">
              <img
                src="https://game.gtimg.cn/images/daojushop/uploads/ad/202206/20220622143800_528795.jpg"
                alt=""
              />
            </Link>
          </div>
          <div className="swiper-slide">
            <Link to="/lol">
              <img
                src="https://game.gtimg.cn/images/daojushop/uploads/ad/202206/20220627010127_701077.jpg"
                alt=""
              />
            </Link>
          </div>
        </div>
        <div className="swiper-pagination"></div>
      </div>
    </Wrapper>
  );
}

效果图如下:

React入门实战——腾讯掌上道聚城主页组件开发

3.2 <ActivitiesInfo/> 活动功能栏组件,<Activities /> 活动栏组件和<GameInfo/> 资讯栏组件

这三个功能组件通过封装axios请求数据函数,从fastmock获取数据。

import axios from 'axios'

export const getActivitiesInfo = () => axios.get('https://www.fastmock.site/mock/cfc81e73033082b126f9464c167c4e75/beers/activiesinfo')

export const getActivities = () => axios.get('https://www.fastmock.site/mock/cfc81e73033082b126f9464c167c4e75/beers/activies')

export const getGameInfo = () => axios.get('https://www.fastmock.site/mock/cfc81e73033082b126f9464c167c4e75/beers/gameinfo')

display:flex弹性布局可以解决移动端大多的css布局。<ActivitiesInfo/>组件 和 <Activities />组件和 <GameInfo/> 资讯栏组件使用display:flex完成一系列的页面布局,且使用了fontawesome的<i className='fa fa-chevron-circle-right icon-right'></i>右箭头跳转图标。这里展示部分代码

// <ActivitiesInfo/>
<Wrapper>
        <div className="item">
          {
              activitiesinfo.map((item) => {
                return (
                  <Link to="/" key={`item${item.id}`} className={`item${item.id}`}>
                    <img src={item.img} alt="" />
                    <span>{item.title}</span>
                  </Link>
                );
              })
          }
        </div>
</Wrapper>
// <Activities/>
<Wrapper>
        <div className="title">
          <h3>精彩活动</h3>
          <a href="/home">
            <i className="fa fa-chevron-circle-right icon-right"></i>
          </a>
        </div>
        <div className="activity">
          {
            activities.map((item) => {
                return (
                <Link
                    to="/home"
                    key={Math.random() * 1000 + item.aid}
                    className={item.aid}
                >
                    <img src={item.img} alt="" />
                    <span>{item.desc}</span>
                </Link>
                );
            })
          }
        </div>
</Wrapper>
// `<GameInfo/>`
<Wrapper>
        <div className="title">
          <h3>精选资讯</h3>
          <a href="/home">
            <i className="fa fa-chevron-circle-right icon-right"></i>
          </a>
        </div>
        <div className="game-info">
          {
            gameinfo.map((item) => {
                return (
                <Link
                    to="/home"
                    key={`info${item.gid}`}
                    className={`game-info${item.gid}`}
                >
                    <img src={item.img} alt="" />
                    <p>{item.desc}</p>
                    <div className="content">
                    <span>{item.author}</span>
                    <i className="iconfont icon-guankan"></i>
                    <span>{item.guankan}</span>
                    <i className="iconfont icon-dianzan"></i>
                    <span>{item.dianzan} </span>
                    </div>
                </Link>
                );
            })
            }
        </div>
</Wrapper>
// 设置`<GameInfo/>`组件左边文字显示效果
        p {
            // 设置文字超过2行则显示为...省略号
            word-break: break-all;
            text-overflow: ellipsis;
            overflow: hidden;
            display: -webkit-box;
            -webkit-box-orient: vertical;
            -webkit-line-clamp: 2; 
        }

效果如下图

React入门实战——腾讯掌上道聚城主页组件开发

3.3 <SaleInfo/> 特惠区组件

同样使用Swiper,<SaleInfo/>组件使用配置swiper的freeMode为true。默认情况下Swiper 每次滑动时只滑动一个Slide,并且会自动贴合Wrapper。开启自由模式后,Swiper 会根据惯性滑动可能不止一格且不会贴合。下面给出swiper的配置

    let swiper = null;
    useEffect(() => {
        if (swiper) return 
        swiper = new Swiper('.sale',{
            observer: true, 
            observeParents: true, 
            freeMode: true
        })
    },[])

效果图如下:

React入门实战——腾讯掌上道聚城主页组件开发

4 实现LOLHome组件

和Home组件类似,LOLHome组件可复用Home组件中的<Banners/> 轮播图组件,<GameInfo/> 资讯栏组件和<ActivitiesInfo/> 活动功能栏组件,其中<ActivitiesInfo/>组件经过修改成拥有轮播图的功能,并添加了<Gift/>组件

4.1 修改后的<ActivitiesInfo/>组件

修改后加入为Swiper增加滚动条,并开启自由模式freeMode,下面只给出swiper配置修改部分的代码

   useEffect(() => {
        if (swiper) return
        swiper = new Swiper('.item', {
            observer: true, 
            observeParents: true, 
            freeMode: true,
            scrollbar: {
                el: '.swiper-scrollbar',
                dragSize: 30,
            },
        })
    }, [])

效果图如下:

React入门实战——腾讯掌上道聚城主页组件开发

4.2 <Gift/>组件

此组件外部同样使用弹性布局felx完成整体布局,内部使用flaot浮动布局完成图片浮动在左边,文字环绕图片居右边。

<Wrapper>
        <div className="title">
          <h3>我的礼包</h3>
          <a href="/home">
            <i className="fa fa-chevron-circle-right icon-right"></i>
          </a>
          {/* <RightOutline /> */}
        </div>
        <div className="gift-info">
          {giftinfo.map((item) => {
            return (
              <Link
                to="/lol"
                key={`info${item.gid}`}
                className={`gift-info${item.gid}`}
              >
                <img src={item.img} alt="" />
                <span>兑换</span>
                <p>{item.desc}</p>
                <p style={{ color: "red" }}>{item.price}</p>
              </Link>
            );
          })}
        </div>
      </Wrapper>

效果图如下:

React入门实战——腾讯掌上道聚城主页组件开发

5. 实现Footer组件

尾部通过 Link 实现页面级路由的跳转,跳转后通过路由判断完成active效果。

<HeaderWrapper>
      <div className="nav-box">
        <i className="iconfont icon-saoyisao"></i>
        <Link
          to="/"
          className={classnames(
            { navitem: true },
            { active: pathname == "/home" || pathname == "/" }
          )}
        >
          精选
        </Link>
        <Link
          to="/lol"
          className={classnames(
            { navitem: true },
            { active: pathname == "/lol" }
          )}
        >
          英雄联盟
        </Link>
        <Link
          to="/cf"
          className={classnames(
            { navitem: true },
            { active: pathname == "/cf" }
          )}
        >
          CF穿越火线
        </Link>
        <Link to="/gamelist">
          <i className="iconfont icon-jiahao icon-right"></i>
        </Link>
      </div>
    </HeaderWrapper>

效果图如下:

React入门实战——腾讯掌上道聚城主页组件开发

最后

到此腾讯掌上道聚城主页组件设计和实现就基本完成了,许多功能和详情页面还没有完成,后续进行完善。希望本文能对小伙伴们有所帮助。

源码地址: 腾讯掌上道聚城

页面预览效果 GitHub Pages

转载自:https://juejin.cn/post/7115693639514226718
评论
请登录