React入门实战——腾讯掌上道聚城主页组件开发
前言
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请求。
项目实现
项目效果图
<LOLHome/>
英雄联盟主页组件
1. 设计思路
掌上道聚城主页的实现,需采用组件化思想,细化主页为以下组件。
-
<Header/>
头部组件 -
<Home/>
精选主页组件(此组件还需细分为其他功能子组件)-
<Banners/>
轮播图组件 -
<ActivitiesInfo/>
活动功能栏组件 -
<Activities />
活动栏组件 -
<GameInfo/>
资讯栏组件 -
<SaleInfo/>
特惠区组件
-
-
<Footer/>
底部组件
另外,英雄联盟专区
首页也需如<Home/>
组件一样细分功能模块,具体的就不再赘述。
根据需求,细分功能完成项目架构,项目目录如下:
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>
);
}
效果图如下:
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>
);
}
效果图如下:
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;
}
效果如下图
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
})
},[])
效果图如下:
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,
},
})
}, [])
效果图如下:
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>
效果图如下:
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>
效果图如下:
最后
到此腾讯掌上道聚城主页组件设计和实现就基本完成了,许多功能和详情页面还没有完成,后续进行完善。希望本文能对小伙伴们有所帮助。
源码地址: 腾讯掌上道聚城
页面预览效果 GitHub Pages
转载自:https://juejin.cn/post/7115693639514226718