文章目录
前言
还记得之前我们创建的 高性能可配置Echarts组件 吗?今天我们将利用它来呈现首页统计模块的数据可视化效果,借助这个组件,我们能够显著减少编写代码的工作量,会方便很多。
Echart模块源码+功能分析+数据渲染
一、HashRateEchart统计图
1. 功能分析
(1)数据获取:使用@tanstack/react-query库来处理数据获取。使用useQuery请求并缓存数据
(2)组件缓存:使用memo高阶组件进行缓存。有助于提高性能,防止不必要的重新渲染组件
(3)数据处理:使用useMemo钩子缓存处理后的图表数据(fullEchartData和echartData),确保只有在必要时才进行数据处理,从而减少不必要的计算
(4)懒加载渲染劫持:组件根据数据的可用性进行条件渲染,数据加载中时显示Loading组件
(5)引用公共组件:使用Echart公共组件,提高开发效率,组件可看之前文章 高性能可配置Echarts图表组件封装
2. 代码+详细注释
// @/components/Home/HashRateEchart/index.tsx
import { memo, useMemo } from "react";
import BigNumber from "bignumber.js";
import { HomeChartBlock, ChartLoadingBlock } from "./styled";
import classNames from "classnames";
import "echarts/lib/chart/line";
import "echarts/lib/component/title";
import echarts from "echarts/lib/echarts";
import { useTranslation } from "react-i18next";
import { useQuery } from "@tanstack/react-query";
import Loading from "@/components/Loading";
import { ReactChartBlock } from "@/components/Echarts/common";
import { queryStatisticHashRate } from '@/api/home'
// echarts 配置
const useOption = () => {
const { t } = useTranslation();
return (data: any, useMiniStyle: boolean): echarts.EChartOption => {
return {
color: ["#ffffff"],
title: {
text: "平均出块时间(s)",
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",
width: 1,
},
},
data: data.map((item: any) => item.xTime),
axisLabel: {
formatter: (value: string) => value,
},
boundaryGap: false,
},
],
yAxis: [
{
position: "left",
type: "value",
scale: true,
axisLine: {
lineStyle: {
color: "#ffffff",
width: 1,
},
},
splitLine: {
lineStyle: {
color: "#ffffff",
width: 0.5,
opacity: 0.2,
},
},
axisLabel: {
formatter: (value: string) => new BigNumber(value),
},
boundaryGap: ["5%", "2%"],
},
{
position: "right",
type: "value",
axisLine: {
lineStyle: {
color: "#ffffff",
width: 1,
},
},
},
],
series: [
{
name: t("block.hash_rate"),
type: "line",
yAxisIndex: 0,
lineStyle: {
color: "#ffffff",
width: 1,
},
symbol: "none",
data: data.map((item: any) => new BigNumber(item.yValue).toNumber()),
},
],
};
};
};
// 使用memo钩子函数提升性能
export default memo(() => {
// 使用useQuery请求数据
const query = useQuery(["StatisticHashRate"], async () => {
const { data,total } = await queryStatisticHashRate({
page: 1,
page_size: 25,
});
return {
data,
total: total ?? data?.length,
};
}, {
refetchOnWindowFocus: false,
});
// 处理数据,并通过useMemo实现数据的缓存
const fullEchartData = useMemo(() => query.data ?? [], [query.data]);
// 获取最近14天的数据,并通过useMemo实现数据的缓存
const echartData = useMemo(() => {
const last14Days = -15;
return fullEchartData.slice(last14Days);
}, [fullEchartData]);
// 根据数据渲染图表,当数据为空时显示没有数据,正在请求数据时显示加载中
if (query.isLoading || !echartData?.length) {
return <ChartLoadingBlock>{query.isLoading ? <Loading size="small" /> : <div className={classNames("no-data")}>暂无数据</div>}</ChartLoadingBlock>;
}
// 获取echarts的option配置
const parseOption = useOption();
return (
<HomeChartBlock to="/block-list">
{/* 使用公共Echart组件 */}
<ReactChartBlock
option={parseOption(echartData, true)}
notMerge
lazyUpdate
style={{
height: "180px",
}}
></ReactChartBlock>
</HomeChartBlock>
);
});
--------------------------------------------------------------------------
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;
}
`;
二、BlockTimeChart统计图
1. 功能分析
注:此处忽略,功能和上面HashRateEchart统计表基本一致,只是数据请求不同
2. 代码+详细注释
// @/components/Home/BlockTimeChart/index.tsx
import { memo, useMemo } from "react";
import BigNumber from "bignumber.js";
import { HomeChartBlock, ChartLoadingBlock } from "./styled";
import classNames from "classnames";
import "echarts/lib/chart/line";
import "echarts/lib/component/title";
import echarts from "echarts/lib/echarts";
import { useTranslation } from "react-i18next";
import { useQuery } from "@tanstack/react-query";
import Loading from "@/components/Loading";
import { ReactChartBlock } from "@/components/Echarts/common";
import { queryStatisticAverageBlockTimes } from '@/api/home'
// echarts 配置
const useOption = () => {
const { t } = useTranslation();
return (data: any, useMiniStyle: boolean): echarts.EChartOption => {
return {
color: ["#ffffff"],
title: {
text: "哈希率(H/s)",
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",
width: 1,
},
},
data: data.map((item: any) => item.xTime),
axisLabel: {
formatter: (value: string) => value,
},
boundaryGap: false,
},
],
yAxis: [
{
position: "left",
type: "value",
scale: true,
axisLine: {
lineStyle: {
color: "#ffffff",
width: 1,
},
},
splitLine: {
lineStyle: {
color: "#ffffff",
width: 0.5,
opacity: 0.2,
},
},
axisLabel: {
formatter: (value: string) => new BigNumber(value),
},
boundaryGap: ["5%", "2%"],
},
{
position: "right",
type: "value",
axisLine: {
lineStyle: {
color: "#ffffff",
width: 1,
},
},
},
],
series: [
{
name: t("block.hash_rate"),
type: "line",
yAxisIndex: 0,
lineStyle: {
color: "#ffffff",
width: 1,
},
symbol: "none",
data: data.map((item: any) => new BigNumber(item.yValue).toNumber()),
},
],
};
};
};
// 使用memo钩子函数提升性能
export default memo(() => {
// 使用useQuery请求数据
const query = useQuery(["StatisticAverageBlockTimes"], async () => {
const { data,total } = await queryStatisticAverageBlockTimes({
page: 1,
page_size: 25,
});
return {
data,
total: total ?? data?.length,
};
}, {
refetchOnWindowFocus: false,
});
// 处理数据,并通过useMemo实现数据的缓存
const fullEchartData = useMemo(() => query.data ?? [], [query.data]);
// 获取最近14天的数据,并通过useMemo实现数据的缓存
const echartData = useMemo(() => {
const last14Days = -15;
return fullEchartData.slice(last14Days);
}, [fullEchartData]);
// 根据数据渲染图表,当数据为空时显示没有数据,正在请求数据时显示加载中
if (query.isLoading || !echartData?.length) {
return <ChartLoadingBlock>{query.isLoading ? <Loading size="small" /> : <div className={classNames("no-data")}>暂无数据</div>}</ChartLoadingBlock>;
}
// 获取echarts的option配置
const parseOption = useOption();
return (
<HomeChartBlock to="/block-list">
{/* 使用公共Echart组件 */}
<ReactChartBlock
option={parseOption(echartData, true)}
notMerge
lazyUpdate
style={{
height: "180px",
}}
></ReactChartBlock>
</HomeChartBlock>
);
});
-------------------------------------------------------------------------------------------------------
// @/components/Home/BlockTimeChart/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;
}
`;
三、使用方式
结合首页响应式构建之banner、搜索、统计模块布局 这一讲,在统计模块中引入出块统计图表,以及挖矿统计图表即可
// 引入组件和echarts
import HashRateEchart from "./HashRateEchart/index";
import BlockTimeChart from "./BlockTimeChart/index";
// 使用
// ....
<HashRateEchart />
// ....
<BlockTimeChart />
// ....
四. 数据渲染后效果如下
(1)PC端
(2)移动端
总结
下一篇讲【首页响应式构建之实现全页面数据】。关注本栏目,将实时更新。