React+TS前台项目实战(十五)-- 全局常用组件Table封装

news2024/11/26 18:28:19

文章目录

  • 前言
  • Table组件
    • 1. 功能分析
    • 2. 代码+详细注释
    • 3. 使用方式
    • 4. 效果展示
  • 总结


前言

在这篇文章中,我们将对本系列项目中常用的表格组件Table进行自定义封装,以提高性能并适应项目需求。后期也可进行修改和扩展,以满足项目的需求。


Table组件

1. 功能分析

(1)定义了两种表格项组件:TableTitleItem 和 TableContentItem
(2)TableTitleItem 用于显示表格的标题,接受 width 和 title 作为属性,将标题显示在指定宽度的行内
(3)TableContentItem 用于显示表格的内容,接受 width、content 和可选的 to 属性。如果有 to 属性,则使用全局封装的Link组件显示带有链接的内容,否则直接显示内容。
(4)使用 memo 优化组件,以提高性能并避免不必要的重新渲染
(5)可自行加下排序等功能,后续本项目有需要再加上

2. 代码+详细注释

// @/components/Table/index.tsx
import { memo, ReactNode, FC } from "react";
import { TableTitleRowItem, TableContentRowItem, HighlightLink } from "./styled";

// 表格标题项组件
interface TableTitleItemProps {
  width: string; // 宽度
  title: string; // 标题
}

const TableTitleItem: FC<TableTitleItemProps> = ({ width, title }) => (
  <TableTitleRowItem width={width}>
    <div>{title}</div> {/* 显示标题 */}
  </TableTitleRowItem>
);

// 表格内容项组件
interface TableContentItemProps {
  width: string; // 宽度
  content: string | ReactNode; // 内容
  to?: string; // 链接地址
}

const TableContentItem: FC<TableContentItemProps> = ({ width, content, to }) => {
  return (
    <TableContentRowItem width={width}>
      {/* 如果有链接地址,则显示高亮链接,否则显示内容 */}
      {to ? <HighlightLink to={to}>{content}</HighlightLink> : content}
    </TableContentRowItem>
  );
};

// 表格标题项组件添加memo性能优化
export const MemoizedTableTitleItem = memo(TableTitleItem);
// 表格内容项组件添加memo性能优化
export const MemoizedTableContentItem = memo(TableContentItem);

--------------------------------------------------------------------------------------------------------------

// @/components/Table/styled.tsx
import styled, { CSSObject } from "styled-components";
import Link from "../Link";
import variables from "@/styles/variables.module.scss";
interface ITableTitleRowItemProps {
  width: string;
}
interface ITableContentRowItemProps {
  width: string;
}
export const TableTitleRow = styled.div`
  background: white;
  display: flex;
  min-height: 65px;
  border-radius: 6px 6px 0 0;
  padding: 0 20px;
  margin-bottom: 4px;

  @media (max-width: ${variables.mobileBreakPoint}) {
    flex-flow: row wrap;
    min-height: auto;
    padding: 5px 20px;
  }
`;

export const TableTitleRowItem = styled.div<ITableTitleRowItemProps>`
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
  width: ${({ width }) => width};
  min-height: 65px;

  div,
  button {
    border: none;
    outline: none;
    background-color: transparent;
    color: #333;
    font-size: 18px;
    font-weight: 450;
    text-align: center;

    @media (max-width: ${variables.largeBreakPoint}) {
      font-size: 16px;
    }
  }

  @media (max-width: ${variables.mobileBreakPoint}) {
    margin: 10px 40px 10px 0;
    min-height: auto;
  }
`;

export const TableContentRow = styled.div`
  position: relative;
  display: flex;
  min-height: 60px;
  background-color: white;
  padding: 20px;

  ::after {
    content: "";
    position: absolute;
    display: block;
    width: auto;
    height: 1px;
    left: 20px;
    right: 20px;
    bottom: 1px;
    background: #d8d8d8;
    transform: ${(): CSSObject => ({
      scaleY: `${Math.ceil((1.0 / window.devicePixelRatio) * 10.0) / 10.0}`,
    })};
  }

  :hover {
    background: #f8f9fa;
  }
`;

export const TableContentRowItem = styled.div<ITableContentRowItemProps>`
  width: ${({ width }) => width};
  color: #000;
  display: flex;
  align-items: center;
  justify-content: center;
  text-overflow: ellipsis;
  font-size: 16px;

  a {
    color: ${({ theme }) => theme.primary};
    &:hover {
      color: ${({ theme }) => theme.primary};
    }
  }
`;

export const HighlightLink = styled(Link)`
  color: ${({ theme }) => theme.primary};
  text-decoration: none;
`;

3. 使用方式

注:这个组件我们模拟一些假数据来演示,可直接复制代码看效果

// @/pages/Nav1/styled.tsx
// 引入组件
import { MemoizedTableContentItem } from "@/components/Table";
// 使用
import { FC, useMemo, useState } from "react";
import { useTranslation } from "react-i18next";
import Content from "@/components/Content";
import { TableTitleRow, TableContentRow, TableTitleRowItem } from "@/components/Table/styled";
import { BlockListPanel, ContentTable } from "./styled";
import { useMediaQuery } from "@/hooks";
import { localeNumberString } from "@/utils/number";
interface TableTitleData {
  title: string; // 表头名称
  width: string; // 表头宽度
}
interface Block {
  number: number; // 块高
  row1Content?: string; // 第一行内容
  row2Content?: string; // 第二行内容
  row3Content?: string; // 第三行内容
  row4Content?: string; // 第四行内容
  width: string; // 表行宽度
  to?: string; // 链接
}
interface TableContentData {
  width: string; // 表格列宽度
  to?: string; // 链接
  content: string; // 表格内容
}
const Nav2Page: FC = () => {
  const [t] = useTranslation();
  const isMaxW = useMediaQuery(`(max-width: 1200px)`);
  const TableTitles: TableTitleData[] = useMemo(
    () => [
      {
        title: "Row1",
        width: isMaxW ? "16%" : "14%",
      },
      {
        title: "Row2",
        width: isMaxW ? "18%" : "11%",
      },
      {
        title: "Row3",
        width: "20%",
      },
      {
        title: "Row4",
        width: isMaxW ? "33%" : "40%",
      },
      {
        title: "Row5",
        width: isMaxW ? "13%" : "15%",
      },
    ],
    [t, isMaxW]
  );
  // 表格数据
  const [tableData] = useState([
    {
      number: 99663.6333663333,
      row1Content: "row1内容",
      row2Content: "row2内容",
      row3Content: "row3内容",
      row4Content: "row4内容",
      width: "16%",
      to: "/Nav3",
    },
    // ...
  ]);
  // 当前页
  const currentPage = 1;
  // 每页数据
  const transferToRowData = (block: Block, page: number, isMaxW: boolean) => {
    return [
      {
        width: isMaxW ? "16%" : "14%",
        to: `/block/${block.number}`,
        content: localeNumberString(block.number),
      },
      {
        width: isMaxW ? "18%" : "11%",
        content: block.row1Content,
      },
      {
        width: "20%",
        content: block.row2Content,
      },
      {
        width: isMaxW ? "33%" : "40%",
        content: block.row3Content,
      },
      {
        width: isMaxW ? "13%" : "15%",
        content: block.row4Content,
      },
    ] as TableContentData[];
  };
  return (
    <Content>
      <BlockListPanel className="container">
        <ContentTable>
          {/* 表头 */}
          <TableTitleRow>
            {TableTitles.map((data: TableTitleData) => (
              <TableTitleRowItem width={data.width} key={data.title}>
                <div>{data.title}</div>
              </TableTitleRowItem>
            ))}
          </TableTitleRow>
          {/* 表内容 */}
          {tableData.map(
            (item: Block) =>
              item && (
                <TableContentRow key={item.number}>
                  {transferToRowData(item, currentPage, isMaxW).map((data: TableContentData) => {
                    return <MemoizedTableContentItem width={data.width} content={data.content} to={data.to} />;
                  })}
                </TableContentRow>
              )
          )}
        </ContentTable>
      </BlockListPanel>
    </Content>
  );
};
export default Nav2Page;

--------------------------------------------------------------------------------------------------------------

// @/pages/Nav1/styled.tsx
import styled from "styled-components";
import variables from "@/styles/variables.module.scss";
export const BlockListPanel = styled.div`
  @media (min-width: ${variables.mobileBreakPoint}) {
    margin-top: 25px;
    margin-bottom: 40px;
    border-radius: 6px;
    overflow: hidden;
    box-shadow: 0 2px 6px 0 rgb(77 77 77 / 21%);
  }

  @media (max-width: ${variables.mobileBreakPoint}) {
    margin-top: 0;
    padding: 0 20px;

    .blockGreenBackground {
      margin-left: -20px;
      height: 61px;
      width: calc(100% + 40px);
      z-index: 1;
    }
  }
`;

export const ContentTitle = styled.div`
  font-size: 50px;
  color: black;
  margin: 0 auto;
  text-align: center;

  @media (max-width: ${variables.mobileBreakPoint}) {
    font-size: 26px;
  }

  &::after {
    content: "";
    background: ${({ theme }) => theme.primary};
    height: 4px;
    width: 197px;
    display: block;
    margin: 0 auto;

    @media (max-width: ${variables.mobileBreakPoint}) {
      width: 80px;
    }
  }
`;

export const ContentTable = styled.div`
  @media (max-width: ${variables.mobileBreakPoint}) {
    margin-top: -41px;
    z-index: 2;
  }
`;

4. 效果展示

在这里插入图片描述


总结

下一篇讲【全局常用组件Pagination封装】。关注本栏目,将实时更新。

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

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

相关文章

Windows 11 安装hp 1020 plus 打印机驱动 (Ubuntu 20.04.3 LTS 部署cups局域网共享打印服务器)

1 win11 下载HP laserjet 1020 plus驱动,可以官网下载哦 链接下载 2 手动添加hp laserjet 1020驱动: 控制面板-->查看设备和打印机-->打印机和扫描仪-->添加设备-->我需要的打印机不在列表中-->通过手动添加-->按名称选择共享打印机 如果找不到&#xff0…

论文《Tree Decomposed Graph Neural Network》笔记

【TDGNN】本文提出了一种树分解方法来解决不同层邻域之间的特征平滑问题&#xff0c;增加了网络层配置的灵活性。通过图扩散过程表征了多跳依赖性&#xff08;multi-hop dependency&#xff09;&#xff0c;构建了TDGNN模型&#xff0c;该模型可以灵活地结合大感受场的信息&…

简易部署的设备日志采集工具

永久免费: Gitee下载 最新版本 使用说明: Moretl 企业级采集文件工具 优势: A. 开箱即用. 解压直接运行.不需额外安装. B. 批管理设备. 设备配置均在后台管理. C. 无人值守 客户端自启动,自更新. D. 稳定安全. 架构简单,内存占用小,通过授权访问.

OPENCV中0x00007FFE5F35F39C发生异常

原因&#xff1a;读取图片时已经为灰度图像&#xff0c;又进行了一次灰度处理cvtColor 解决方法&#xff1a;如上图所示&#xff0c;将cv::imread的第二个参数改为cv::IMREAD_COLOR&#xff1b;或者保留cv::IMREAD_GRAYSCALE&#xff0c;删去后面的cv::cvtColor

高通安卓12-OTA 升级

1.OTA介绍 OTA 英文全称是 Over-the-Air Technology&#xff0c;即空间下载技术的意思。 OTA 升级是 Android 系统提供的标准软件升级方式。它功能强大&#xff0c;可以无损失升级系统&#xff0c;主 要通过网络[例如 WIFI、3G]自动下载 OTA 升级包、自动升级&#xff0c;但…

仿饿了么加入购物车旋转控件 - 自带闪转腾挪动画 的按钮

, mWidth - mCircleWidth, mHeight - mCircleWidth); canvas.drawRoundRect(rectF, mHintBgRoundValue, mHintBgRoundValue, mHintPaint); //前景文字 mHintPaint.setColor(mHintFgColor); // 计算Baseline绘制的起点X轴坐标 int baseX (int) (mWidth / 2 - mHintPaint.m…

新闻管理与推荐系统Python+Django+协同过滤推荐算法+管理系统

一、介绍 新闻管理与推荐系统。本系统使用Python作为主要开发语言开发的一个新闻管理与推荐的网站平台。 网站前端界面采用HTML、CSS、BootStrap等技术搭建界面。后端采用Django框架处理用户的逻辑请求&#xff0c;并将用户的相关行为数据保存在数据库中。通过Ajax技术实现前后…

mayavi pyqt 实例

目录 安装&#xff1a; 示例代码&#xff1a; 生成3d检测框&#xff1a; 安装&#xff1a; pip install pyqt5 mayavi traits traitsui 示例代码&#xff1a; import sys from PyQt5.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QWidget, QPushButton from …

区块链中nonce是什么,什么作用

目录 区块链中nonce是什么,什么作用 区块链中nonce是什么,什么作用 Nonce在以太坊中是一个用于确保交易顺序性和唯一性的重要参数。以下是对Nonce的详细解释: 定义 Nonce是一个scalar值,它等于从该地址发送的交易数量,或在具有关联代码的账户的情况下,由该账户创建的合…

【Flutter 专题】112 图解自定义 ACEPieWidget 饼状图 (一)

类别选项球&#xff1b;切割绘制饼状图&#xff1b;饼状图中绘制文字&#xff1b; 1. 类别选项球 对于两侧不同颜色类别选项卡&#xff0c;仅需要简单设置一下 Container 的 decoration 装饰器即可&#xff0c;只是方便用户查看饼状图分类而已&#xff1b; return Container…

不用写一行代码,deepseek结合腾讯云语音识别来批量转录Mp3音频

首先&#xff0c;打开window系统中的cmd命令行工具&#xff0c;或者powershell&#xff0c;安装腾讯云tencentcloud的Python库 pip install -i https://mirrors.tencent.com/pypi/simple/ --upgrade tencentcloud-sdk-python 然后&#xff0c;开通腾讯云的对象存储COS服务&…

【小沐学AI】Python实现语音识别(Whisper-Web)

文章目录 1、简介2、下载2.1 openai-whisper2.2 whisper-web 结语 1、简介 https://openai.com/index/whisper/ Whisper 是一种自动语音识别 &#xff08;ASR&#xff09; 系统&#xff0c;经过 680,000 小时的多语言和多任务监督数据的训练&#xff0c;从网络上收集。我们表…

【大数据 复习】第8章 Hadoop架构再探讨

一、概念 1.Hadoop1.0的核心组件&#xff08;仅指MapReduce和HDFS&#xff0c;不包括Hadoop生态系统内的Pig、Hive、HBase等其他组件&#xff09;&#xff0c;主要存在以下不足&#xff1a; &#xff08;1&#xff09;抽象层次低&#xff0c;需人工编码 &#xff08;2&#xf…

Docker常用命令与实战示例

docker 1. 安装2. 常用命令3. 存储4. 网络5. redis主从复制示例6. wordpress示例7. DockerFile8. 一键安装超多中间件&#xff08;compose&#xff09; 1. 安装 以centOS系统为例 # 移除旧版本docker sudo yum remove docker \docker-client \docker-client-latest \docker-c…

AI时代的音乐革命:创作更简单,灵魂在哪里?

#AI在创造还是毁掉音乐# 我是李涛&#xff0c;一名音乐创作者&#xff0c;最近一直在思考一个问题&#xff1a;AI到底是在创造音乐&#xff0c;还是在毁掉音乐&#xff1f; 几个月前&#xff0c;我第一次接触到AI音乐创作工具。它让我震惊&#xff0c;只需要输入几个关键词&a…

数据结构7---图

一、定义 对于图的定义&#xff0c;我们需要明确几个注意的地方:一线性表中我们把数据元素叫元素&#xff0c;树中叫结点&#xff0c;在途中数据元素我们则称之为顶点(Vertex)。 对于图的定义&#xff0c;我们需要明确几个注意的地方: 线性表中我们把数据元素叫元素&#xf…

实现文件分片合并功能并使用Github Actions自动编译Release

一、编译IOS镜像 1.1 编译 起因是公司电脑使用的Win11 23H2的预览版&#xff0c;这个预览版系统的生命周期只到2024-09-18&#xff0c;到期后就会强制每两小时重启。这是Windows强制升级系统的一种手段。 虽然公司里的台式电脑目前用不到&#xff0c;但是里面还保留许多旧项…

Jenkins定时构建自动化(一):Jenkins下载安装配置

目录 ​编辑 一、jdk下载安装 1. 已下载安装jdk 2. 未下载安装jdk 二、jenkins安装 1. .war包安装 三、获取IP地址 四、jenkins网页配置 一、jdk下载安装 1. 已下载安装jdk &#xff08;1&#xff09;查询jdk版本命令&#xff1a;java -version &#xff08;2&#xff09;…

[SAP ABAP] 运算符

1.算数运算符 算术运算符描述加法-减法*乘法/除法MOD取余 示例1 输出结果: 输出结果: 2.比较运算符 比较运算符描述示例 等于 A B A EQ B <> 不等于 A <> B A NE B >大于 A > B A GT B <小于 A < B A LT B >大于或等于 A > B A GE B <小…

Html去除a标签的默认样式

Html去除a标签的默认样式, a标签超链接字体默认蓝色带下划线; 去除可用: a{text-decoration:none;color:inherit;cursor:auto; }测试代码 <!DOCTYPE html> <html lang"zh-CN" dir"ltr"><head><meta charset"utf-8"/>&…