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;因此一直以来都被视为传播的重要元素。这种能力来自于通过布局和视觉线…

在Pycharm中把jupyter notebook转换成md格式

在Pycharm的控制台输入&#xff1a; jupyter nbconvert --to markdown filename.ipynb这里实际上是用的nvconvert 同理&#xff0c;如果是在vscode中写jupyter&#xff0c;也可以用&#xff1a; jupyter nbconvert --to FORMAT notebook.ipynb将其变成ipynb文件&#xff08;…

普通人必看!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;判断评论是正面…

Jackson中ObjectMapper

文章目录 概要ObjectMapper常用方法将Java对象转换为JSON字符串从JSON字符串转换为Java对象读取JSON文件并解析为树结构 概要 ObjectMapper 是 Jackson 数据处理库的核心类&#xff0c;用于将 Java 对象转换为 JSON&#xff0c;以及将 JSON 转换为 Java 对象。 ObjectMapper常…

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…

Android Camera API发展历程

Android Camera API发展历程 一、Android Camera API介绍 Android系统中Camera API是用于控制相机设备的主要API&#xff0c;到目前为止&#xff0c;Camera API历史上共历经了三版重要的API。 在Android 5.0之前&#xff0c;主要使用的是Camera API1&#xff0c;但现在已经弃…

如何使用 Puppeteer 避免机器人检测?

为什么有反机器人系统&#xff1f; 保护网站资源和性能 爬虫和机器人程序在短时间内可以发送大量请求&#xff0c;消耗服务器资源&#xff0c;导致网站性能下降甚至崩溃。 反机器人系统可以帮助网站管理和限制这些请求&#xff0c;从而保持网站的稳定性和可用性。 防止数据…

借助软件资产管理系统,优化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…

TEE共享内存的介绍-共享内存的限制是什么? TA堆内存/栈内存有限制吗?Trustzone/TEE

快速链接: . 👉👉👉 个人博客笔记导读目录(全部) 👈👈👈 付费专栏-付费课程 【购买须知】:【精选】TEE从入门到精通-[目录] 👈👈👈思考: 如何开发一个TA? sdk又是什么?开发一个TA的流程是怎样的?How to do?有关TA的签名介绍TEE开发Secure driver介绍RP…

昇思25天学习打卡营第21天|基于MindSpore实现BERT对话情绪识别

模型简介 BERT全称是来自变换器的双向编码器表征量。与BERT模型相似的预训练语言模型例如问答、命名实体识别、自然语言推理、文本分类等在许多自然语言处理任务中发挥着重要作用。模型是基于Transformer中的Encoder并加上双向的结构。 BERT模型的主要创新点都在pre-train方法…

SCI丨返修一作+通讯

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

Nginx 配置ssl证书

1. 准备 SSL 证书文件 确保您有以下文件&#xff1a; SSL 证书文件&#xff08;通常是 .crt 或 .pem 文件&#xff09; 私钥文件&#xff08;通常是 .key 文件&#xff09; 中间证书文件&#xff08;如果适用&#xff0c;通常是 .crt 或 .pem 文件&#xff09; 将这些文件上传…

苍穹外卖--完善登录功能:进行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…