React+TS前台项目实战(二十七)-- 首页响应式构建之banner、搜索、统计模块布局

文章目录

  • 前言
  • 一、 效果展示
  • 二、相关模块
    • 1. Statistic统计模块
      • 功能分析
      • 代码+详细注释
      • 使用方式
    • 2. Search搜索模块
      • 功能分析
      • 代码+详细注释
      • 使用方式
    • 3. banner模块
      • 功能分析
      • 代码+详细注释
      • 使用方式
  • 总结


前言

前面我们已经封装了这个项目基本要用到的全局组件了,现在就开始进入页面构建以及接口对接阶段了。首先,我们先来构建首页响应式布局,接下来会讲到真实接口对接,搭配react-query实现轮询,并使用memo,useMemo,usePrevious等钩子来优化页面,避免不必要的重新渲染。

一、 效果展示

在这里插入图片描述

二、相关模块

1. Statistic统计模块

功能分析

该模块主要为了展示基本数据统计,以及Echart图表统计

代码+详细注释

(1) 图表统计模块抽离

// @/pages/Home/StaticBlock/HashRateEchart/index.tsx
import { memo } from "react";
import BigNumber from "bignumber.js";
import "echarts/lib/chart/line";
import "echarts/lib/component/title";
import echarts from "echarts/lib/echarts";
import { useTranslation } from "react-i18next";
import { HomeChartBlock } from "./styled";
import { ReactChartBlock } from "@/components/Echarts/common";
// 使用useOption函数生成Echarts配置对象
const useOption = () => {const { t } = useTranslation();return (data: any, useMiniStyle: boolean): echarts.EChartOption => {return {color: ["#ffffff"], // 颜色设置title: {text: "图表y轴时间", // 标题textAlign: "left", // 标题对齐方式textStyle: {color: "#ffffff", // 字体颜色fontSize: 14, // 字体大小fontWeight: "lighter", // 字体粗细fontFamily: "Lato", // 字体类型},},grid: {left: useMiniStyle ? "1%" : "2%", // 图表距离容器左边的距离right: "3%", // 图表距离容器右边的距离top: useMiniStyle ? "20%" : "15%", // 图表距离容器顶部的距离bottom: "2%", // 图表距离容器底部的距离containLabel: true, // 是否包含坐标轴的刻度标签},xAxis: [{axisLine: {lineStyle: {color: "#ffffff", // x轴颜色width: 1, // x轴宽度},},data: data.map((item: any) => item.xTime), // x轴数据axisLabel: {formatter: (value: string) => value, // x轴坐标标签格式化},boundaryGap: false, // 是否留空},],yAxis: [{position: "left",type: "value",scale: true,axisLine: {lineStyle: {color: "#ffffff", // y轴颜色width: 1, // y轴宽度},},splitLine: {lineStyle: {color: "#ffffff", // y轴分割线颜色width: 0.5, // y轴分割线宽度opacity: 0.2, // y轴分割线透明度},},axisLabel: {formatter: (value: string) => new BigNumber(value), // y轴坐标标签格式化},boundaryGap: ["5%", "2%"], // y轴两侧留空},{position: "right",type: "value",axisLine: {lineStyle: {color: "#ffffff", // y轴颜色width: 1, // y轴宽度},},},],series: [{name: t("block.hash_rate"), // 系列名称type: "line", // 系列类型yAxisIndex: 0, // y轴索引lineStyle: {color: "#ffffff", // 系列颜色width: 1, // 系列线条宽度},symbol: "none", // 系列标记的图形类型data: data.map((item: any) =>new BigNumber(item.yValue).toNumber()), // 系列数据},],};};
};
// HomeChartBlock组件
export default memo(() => {// 后期改为真实接口请求const echartData = [{ xTime: "2020-01-01", yValue: "1500" },{ xTime: "2020-01-02", yValue: "5220" },{ xTime: "2020-01-03", yValue: "4000" },{ xTime: "2020-01-04", yValue: "3500" },{ xTime: "2020-01-05", yValue: "7800" },];// 解析配置对象const parseOption = useOption();return (<HomeChartBlock to="/block-list">{/* 使用ReactChartBlock组件展示Echarts图表 */}<ReactChartBlockoption={parseOption(echartData, true)}notMergelazyUpdatestyle={{height: "180px",}}></ReactChartBlock></HomeChartBlock>);
});
--------------------------------------------------------------------------------------------------------------
// @/pages/Home/StaticBlock/HashRateEchart/styled.tsx
import styled from "styled-components";
import Link from "@/components/Link";
export const HomeChartBlock = styled(Link)`canvas {cursor: pointer;}
`;
export const ChartLoadingBlock = styled.div`height: 100%;display: flex;align-items: center;justify-content: center;.no-data {font-size: 18px;}
`;

(2)引入统计图表

// @/pages/Home/StatisticBlock/index.tsx
import { FC } from "react";
import classNames from "classnames";
import { useTranslation } from "react-i18next";
import HashRateEchart from "./HashRateEchart/index";
import { HomeStatisticBlock, HomeStatisticItem } from "./styled";
import { useStatistics } from './hook'
const StatisticBlock: FC = () => {// 区块链统计数据类型声明interface EchartsAndData {name: string;value: string;}// 使用区块链统计数据const useEchartsAndDataList = (): EchartsAndData[] => {const { t } = useTranslation();const statistics = useStatistics()return [{name: t("home.echartsAndData.name1"),value: t(statistics.value1),},{name: t("home.echartsAndData.name2"),value: t(statistics.value2),},{name: t("home.echartsAndData.name3"),value: t(statistics.value3),},{name: t("home.echartsAndData.name4"),value: t(statistics.value4),},];};// 使用区块链统计数据const echartsAndDataList = useEchartsAndDataList();// 单个统计渲染组件const StatisticItem = ({ data }: { data: EchartsAndData }) => (<HomeStatisticItem><div className={classNames("statistic-item-left-title")}>{data.name}</div><div className={classNames("statistic-item-left-value")}>{data.value}</div></HomeStatisticItem>);return (<><HomeStatisticBlock><div className={classNames("statistic-item")}><div className={classNames("statistic-item-left")}><StatisticItem data={echartsAndDataList[0]}></StatisticItem><StatisticItem data={echartsAndDataList[1]}></StatisticItem></div><div className={classNames("statistic-item-right")}>{/* hash图表模拟 */}<HashRateEchart /></div></div><div className={classNames("statistic-item")}><div className={classNames("statistic-item-left")}><StatisticItem data={echartsAndDataList[2]}></StatisticItem><StatisticItem data={echartsAndDataList[3]}></StatisticItem></div><div className={classNames("statistic-item-right")}>{/* hash图表模拟 */}<HashRateEchart /></div></div></HomeStatisticBlock></>);
};
export default StatisticBlock;
--------------------------------------------------------------------------------------------------------------
// @/pages/Home/StatisticBlock/styled.tsx
import styled from "styled-components";
import variables from "@/styles/variables.module.scss";
export const HomeStatisticBlock = styled.div`width: 100%;height: 207px;display: flex;margin-bottom: 20px;.statistic-item {display: flex;align-items: center;justify-content: space-between;flex: 1;background: #232323;@media (max-width: ${variables.extraLargeBreakPoint}) {flex-direction: column;}@media (max-width: ${variables.mobileBreakPoint}) {}.statistic-item-left {flex: 1;width: 100%;height: 100%;}.statistic-item-right {flex: 2;width: 100%;height: 100%;padding: 10px;// background: linear-gradient(304deg, #6e85e0 2%, #577cdb 48%, #486ecc 99%);@media (max-width: ${variables.extraLargeBreakPoint}) {}@media (max-width: ${variables.mobileBreakPoint}) {}}&:last-child {background: #484e4e;}}@media (max-width: ${variables.extraLargeBreakPoint}) {height: 310px;}@media (max-width: ${variables.mobileBreakPoint}) {flex-direction: column;height: auto;}
`;
export const HomeStatisticItem = styled.div`padding: 30px;display: flex;justify-content: space-between;flex-direction: column;color: #fff;.statistic-item-left-title {font-size: 14px;margin-bottom: 5px;}.statistic-item-left-value {font-size: 18px;font-weight: bold;}@media (max-width: ${variables.extraLargeBreakPoint}) {padding: 15px 30px;flex-direction: row;margin-bottom: 0;.statistic-item-left-value {font-size: 16px;}}@media (max-width: ${variables.mobileBreakPoint}) {padding: 10px 20px;}
`;

使用方式

// 引入
import StatisticBlock from "./SearchBlock";
// 使用
<StatisticBlock />

2. Search搜索模块

功能分析

(1)引入全局封装的搜索组件,抽离成一个灵巧组件
(2)使用国际化语言

代码+详细注释

// @/pages/Home/SearchBlock/index.tsx
import { FC, memo } from "react";
import { useTranslation } from "react-i18next";
import classNames from "classnames";
import styles from "./index.module.scss";
import Search from "@/components/Search";
// SearchBlock 组件
const SearchBlock: FC = memo(() => {// 获取 i18n 的翻译函数const [t] = useTranslation();return (<div className={classNames(styles.searchBlock)}>{/* 标题 */}<span className={classNames(styles.title)}>{t("common.Explorer")}</span>{/* 内容 */}<div className={classNames(styles.content)}>{/* 搜索组件 */}<Search hasButton /></div></div>);
});
// 导出 SearchBlock 组件
export default SearchBlock;
--------------------------------------------------------------------------------------------------------------
// @/pages/Home/SearchBlock/index.module.scss
@import "@/styles/variables.module";
.searchBlock {display: flex;align-items: center;margin: 20px 0;.title {display: flex;align-items: center;font-weight: 800;font-size: 20px;@media (max-width: $extraLargeBreakPoint) {margin-bottom: 20px;}@media (max-width: $mobileBreakPoint) {font-size: 16px;margin-bottom: 14px;}}.content {flex: 1;margin-left: 16px;@media (max-width: $extraLargeBreakPoint) {width: 100%;margin-left: 0;}}@media (max-width: $extraLargeBreakPoint) {display: block;}
}

使用方式

// 引入
import SearchBlock from "./SearchBlock";
// 使用
<SearchBlock />

3. banner模块

功能分析

banner展示图,此处PC端和移动端采用不同的图片

代码+详细注释

// @/pages/Home/Banner/index.tsx
import classNames from "classnames";
import styles from "./index.module.scss";
export default () => <div className={classNames(styles.banner)} />;
--------------------------------------------------------------------------------------------------------------
// @/pages/Home/Banner/index.module.scss
@import "@/styles/variables.module";
$backgroundColor: #232323;
.banner {width: 100%;height: 200px;background: url("./assets/banner.svg") no-repeat center center / auto 100%;background-color: $backgroundColor;position: relative;@media (max-width: $mobileBreakPoint) {background-image: url("./assets/banner_phone.svg");}
}

使用方式

// 引入
import Banner from "./Banner";
// 使用
<Banner />

总结

下一篇讲【首页响应式构建之区块、交易列表布局】。关注本栏目,将实时更新。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/43302.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ScreenAI ——能理解从信息图表到用户界面的图像和文本算法解析

概述 论文地址&#xff1a;https://arxiv.org/pdf/2402.04615.pdf 信息图表&#xff08;图表、示意图、插图、地图、表格、文档布局等&#xff09;能够将复杂的数据和想法转化为简单的视觉效果&#xff0c;因此一直以来都被视为传播的重要元素。这种能力来自于通过布局和视觉线…

普通人必看!AI绘画商业变现全攻略(附教程)

大部分的设计师除了主业以外&#xff0c;都会利用空余时间去接单做副业。 单子包括但不限于产品/品牌LOGO、电商产品图设计、海报、室内设计图等等&#xff0c;单价在几十到上千不等 引起了我的思考&#xff0c;我们普通人有没有机会&#xff0c;也能像他们一样去接单赚钱吗&a…

pytorch- RNN循环神经网络

目录 1. why RNN2. RNN3. pytorch RNN layer3.1 基本单元3.2 nn.RNN3.2.1 函数说明3.2.2 单层pytorch实现3.2.3 多层pytorch实现 3.3 nn.RNNCell3.3.1 函数说明3.3.2 单层pytorch实现3.3.3 多层pytorch实现 4.完整代码 1. why RNN 以淘宝的评论为例&#xff0c;判断评论是正面…

matplotlib颜色对照表

matplotlib的色彩设置: #------------------------------------------------------------------------------------------------------------------------------- #-------------------------------------------------------------------------------------------------------…

【JavaWeb】登录校验-会话技术(二)JWT令牌

JWT令牌 介绍 JWT全称&#xff1a;JSON Web Token &#xff08;官网&#xff1a;https://jwt.io/&#xff09; 定义了一种简洁的、自包含的格式&#xff0c;用于在通信双方以json数据格式安全的传输信息。由于数字签名的存在&#xff0c;这些信息是可靠的。 简洁&#xff1a…

vue和react你怎么选择?

在选择Vue和React之间&#xff0c;其实没有一个绝对的“最佳选择”&#xff0c;因为这取决于你的项目需求、团队熟悉度、开发环境、以及你对这两个框架的个人偏好。下面是一些可以帮助你做出决策的因素&#xff1a; 1. 学习曲线 Vue&#xff1a;Vue的学习曲线相对平缓&#xf…

借助软件资产管理系统,优化Solidworks软件许可证管理

在当今数字化的企业环境中&#xff0c;软件许可证的有效管理对于业务的顺畅运行至关重要。然而&#xff0c;IT 运维部门常常面临着诸如用户部门 SW 许可证不够用、使用紧张等问题&#xff0c;而由于缺乏可靠的数据支持&#xff0c;难以准确判断许可证的短缺程度&#xff0c;这给…

MFC引用C#生成的dll,将dll放置到非exe程序目录,如何操作?

&#x1f3c6;本文收录于「Bug调优」专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收藏&&…

信创:鲲鹏(arm64)+麒麟(kylin v10)离线部署k8s和kubesphere(含离线部署新方式)

本文将详细介绍&#xff0c;如何基于鲲鹏CPU(arm64)和操作系统 Kylin V10 SP2/SP3&#xff0c;利用 KubeKey 制作 KubeSphere 和 Kubernetes 离线安装包&#xff0c;并实战部署 KubeSphere 3.3.1 和 Kubernetes 1.22.12 集群。 服务器配置 主机名IPCPUOS用途master-1192.168.10…

【linux高级IO(二)】多路转接之select详解

&#x1f493;博主CSDN主页:杭电码农-NEO&#x1f493;   ⏩专栏分类:Linux从入门到精通⏪   &#x1f69a;代码仓库:NEO的学习日记&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学更多操作系统知识   &#x1f51d;&#x1f51d; Linux高级IO 1. 前言2. 初识s…

SCI丨返修一作+通讯

中科四区&#xff0c;JCR2 返修转让一作通讯&#xff0c;5个月左右录用 题目&#xff1a;通过机器学习算法XXXXXXXxxx混凝土力学性能的可靠方法

苍穹外卖--完善登录功能:进行MD5加密

目标 TODO&#xff1a;使用MD5加密方式对明文密码。 实现 password DigestUtils.md5DigestAsHex(password.getBytes());

Face_recognition实现人脸识别

这里写自定义目录标题 欢迎使用Markdown编辑器一、安装人脸识别库face_recognition1.1 安装cmake1.2 安装dlib库1.3 安装face_recognition 二、3个常用的人脸识别案例2.1 识别并绘制人脸框2.2 提取并绘制人脸关键点2.3 人脸匹配及标注 欢迎使用Markdown编辑器 本文基于face_re…

双向链表+Map实现LRU

LRU: LRU是Least Recently Used的缩写&#xff0c;即最近最少使用&#xff0c;是一种常用的页面置换算法&#xff0c;选择最近最久未使用的页面予以淘汰。 核心思想&#xff1a; 基于Map实现k-v存储&#xff0c;双向链表中使用一个虚拟头部和虚拟尾部&#xff0c;虚拟头部的…

BioXcell—InVivoMAb anti-West Nile/dengue virus E protein

研发背景&#xff1a; 西尼罗河病毒(WNV)是一种由蚊虫类介导传播的黄病毒&#xff0c;与引起人类感染性流行病的登革热病毒、黄热病病毒和日本脑炎病毒密切相关。 WNV和登革热病毒(DENV)同属黄病毒科&#xff08;Flaviviridae&#xff09;黄热病毒属&#xff0c;是具有小包膜单…

【多模态】41、VILA | 打破常规多模态模型训练策略,在预训练阶段就微调 LLM 被证明能取得更好的效果!

论文&#xff1a;VILA: On Pre-training for Visual Language Models 代码&#xff1a;https://github.com/NVlabs/VILA 出处&#xff1a;NVLabs 时间&#xff1a;2024.05 贡献&#xff1a; 证明在预训练阶段对 LLM 进行微调能够提升模型对上下文任务的效果在 SFT 阶段混合…

Centos7离线安装ElasticSearch7.4.2

一、官网下载相关的安装包 ElasticSearch7.4.2&#xff1a; elasticsearch-7.4.2-linux-x86_64.tar.gz 下载中文分词器&#xff1a; elasticsearch-analysis-ik-7.4.2.zip 二、上传解压文件到服务器 上传到目录&#xff1a;/home/data/elasticsearch 解压文件&#xff1…

免费无限白嫖阿里云服务器

今天&#xff0c;我来分享一个免费且无限使用阿里云服务器的方法&#xff0c;零成本&#xff01;这适用于日常测试学习&#xff0c;比如测试 Shell 脚本、学习 Docker 安装、MySQL 等等。跟着我的步骤&#xff0c;你将轻松拥有一个稳定可靠的服务器&#xff0c;为你的学习和实践…

错误记录-SpringCloud-OpenFeign测试远程调用

文章目录 1&#xff0c;org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name memberController: Unsatisfied dependency expressed through field couponFeign2&#xff0c; Receiver class org.springframework.cloud.netflix…

几种不同的方式禁止IP访问网站(PHP、Nginx、Apache设置方法)

1、PHP禁止IP和IP段访问 <?//禁止某个IP$banned_ip array ("127.0.0.1",//"119.6.20.66","192.168.1.4");if ( in_array( getenv("REMOTE_ADDR"), $banned_ip ) ){die ("您的IP禁止访问&#xff01;");}//禁止某个IP段…