移动端 h5-table react版本支持虚拟列表

介绍

适用于 react + ts 的 h5 移动端项目 table 组件

github 链接 :https://github.com/duKD/react-h5-table

有帮助的话 给个小星星

有两种表格组件
常规的:
支持 左侧固定 滑动 每行点击回调 支持 指定列排序 支持滚动加载更多

效果和之前写的vue3 版本类似
vue3 h5 表格

请添加图片描述

大数据量时 使用虚拟列表:
也支持 左侧固定 滑动 每行点击回调 支持 指定列排序 不支持滚动加载

请添加图片描述

开始

npm i @lqcoder/react-h5-table

入口 引入table样式文件

import "@lqcoder/react-h5-table/scripts/style.css";

常规版使用

相关 props 配置 说明

export type tablePropsType<T = any> = {
  rowKey?: string; //表格行 key 的取值字段 默认取id字段
  minTableHeight?: number; //表格最小高度
  showRowNum?: number; // 表格显示几行
  headerHeight?: number; // 头部默认高度
  rowHeight?: number; //每行数据的默认高度
  column: Array<columnItemType<T>>;
  tableData: Array<T>;
  clickOptions?: clickOptions<T>; // 是否需要处理点击事件
  disable?: boolean; // 是否启用下拉加载
  pullDownProps?: pullDownPropsType;
  changePullDownProps?: (args: pullDownPropsType) => void; // 修改加载状态
  handleHeadSortClick?: (propsKey: string, type: sortStatusType) => void;
  onload?: () => void; // 数据加载
  rootValue?: number; //
};



export type columnItemType<T = any> = {
  title: string; // 列名
  dataIndex: string; // table data key 值
  width: number; // 列 宽度
  sortable?: boolean; //是否 支持排序
  align?: "left" | "center" | "right"; // 布局
  render?: (item: T, index?: number) => any; //自定义单元格显示的内容
};

// 下拉加载相关配置
export type pullDownPropsType = {
  error?: boolean; // 数据加载失败
  loading?: boolean; // 数据处于加载状态
  finish?: boolean; // 数据 是否完全加载
  loadingText?: string; // 加载文案
  errorText?: string; // 失败文案
  finishedText?: string; // 完成文案
  offset?: number; //触发加载的底部距离
};

//  点击相关配置
export type clickOptions<T> = {
  clickRender: (item: T, index: number) => React.JSX.Element; // 点击列触发渲染
  clickHeight: number; // 显示栏的高度 
};

代码示例:


// App.tsx 文件
import { useRef, useState } from "react";
import {
  H5Table,
  clickOptions,
  columnItemType,
  sortStatusType,
} from "@lqcoder/react-h5-table";

import Styles from "./App.module.scss";

function App() {
  type dataType = {
    id: number;
    type?: number;
    select: string;
    position: string;
    use: string;
    markValue: string;
    cur: string;
    cost: string;
    newPrice: number;
    float: string;
    profit: string;
    count: string;
  };
  const column: Array<columnItemType<dataType>> = [
    {
      title: "班费/总值",
      width: 250,
      dataIndex: "rateAndSum",
      render(item, _index) {
        return (
          <section className="nameAndMarkValue">
            <div className="name">
              {item.select}
              <span className="type">{item.type === 1 ? "深" : "沪"}</span>
            </div>
            <div className="markValue">
              {item.markValue}=={item.id}
            </div>
          </section>
        );
      },
      align: "left",
    },
    {
      title: "持仓/可用",
      dataIndex: "positionAndUse",
      sortable: true,
      width: 200,
      align: "right",
      render(item, _index) {
        return (
          <section className="positionAndUse">
            <div className="position">{item.position}</div>
            <div className="use">{item.use}</div>
          </section>
        );
      },
    },
    {
      title: "现价/成本",
      dataIndex: "curAndCost",
      sortable: true,
      width: 200,
      align: "right",
      render(item) {
        return (
          <section className="curAndCost">
            <div className="cur">{item.cur}</div>
            <div className="cost">{item.cost}</div>
          </section>
        );
      },
    },
    {
      title: "浮动/盈亏",
      dataIndex: "float",
      width: 200,
      align: "right",
      render(item) {
        return (
          <section className="floatAndProfit">
            <div className="float">{item.float}</div>
            <div className="profit">{item.profit}</div>
          </section>
        );
      },
    },
    {
      title: "账户资产",
      dataIndex: "count",
      width: 200,
    },
  ];

  const temp = Array.from({ length: 20 }).map((item, index) => {
    return {
      id: index,
      select: "三年二班",
      type: 1,
      position: `${27000 + index * 10}`,
      use: "5,000",
      markValue: "500,033.341",
      cur: "30.004",
      cost: "32.453",
      newPrice: 20,
      float: "+18,879.09",
      profit: "-5.45%",
      count: "120,121",
    };
  });

  const dataRef = useRef(temp);

  const [data, setData] = useState(temp);

  const [pullDownProps, setPullDownProps] = useState({
    offset: 10,
    error: false, // 数据加载失败
    loading: false, // 数据处于加载状态
    finish: false, // 数据 是否完全加载
    loadingText: "加载中...", // 加载文案
    errorText: "出错了", // 失败文案
    finishedText: "到底了", // 完成文案
  });

  const onload = () => {
    setTimeout(() => {
      const len = data.length;
      setData(
        data.concat(
          Array.from({ length: 10 }).map((item, index) => {
            return {
              id: len + index,
              select: "三年二班",
              type: 1,
              position: "28000",
              use: "5,000",
              markValue: "500,033.341",
              cur: "30.004",
              cost: "32.453",
              newPrice: 20,
              float: "+18,879.09",
              profit: "-5.45%",
              count: "120,121",
            };
          })
        )
      );
      dataRef.current = dataRef.current.concat(
        Array.from({ length: 10 }).map((item, index) => {
          return {
            id: len + index,
            select: "三年二班",
            type: 1,
            position: "28000",
            use: "5,000",
            markValue: "500,033.341",
            cur: "30.004",
            cost: "32.453",
            newPrice: 20,
            float: "+18,879.09",
            profit: "-5.45%",
            count: "120,121",
          };
        })
      );
      setPullDownProps({
        ...pullDownProps,
        loading: false,
      });
    }, 1000);
  };

  const changePullDownProps = (args: any) => {
    setPullDownProps(args);
  };

  /**
   * 处理排序按钮回调 处理逻辑交给开发
   * @param propsKey 点击的列名
   * @param type 0 默认 1 升 2 降
   * @returns
   */
  const handleHeadSortClick = (propsKey: string, type: sortStatusType) => {
    if (type === 0) {
      setData(dataRef.current);
      return;
    }
    if (propsKey === "positionAndUse") {
      if (type === 1) {
        const temp = [...dataRef.current].sort(
          (a, b) => Number(b.position) - Number(a.position)
        );
        setData(temp);
      } else {
        const temp = [...dataRef.current].sort(
          (a, b) => Number(a.position) - Number(b.position)
        );
        setData(temp);
      }
    }

    if (propsKey === "curAndCost") {
      if (type === 1) {
        const temp = [...dataRef.current].sort(
          (a, b) => Number(b.cur) - Number(a.cur)
        );
        setData(temp);
      } else {
        const temp = [...dataRef.current].sort(
          (a, b) => Number(a.cur) - Number(b.cur)
        );
        setData(temp);
      }
    }
  };

  const handelSell = () => {
    console.log("handelSell----");
  };

  const clickOptions: clickOptions<dataType> = {
    clickRender(item, index) {
      return (
        <section className={Styles["rowDownMark"]}>
          <div className={Styles["rowDownMark-item"]} onClick={handelSell}>
            买入
          </div>
          <div className={Styles["rowDownMark-item"]}>卖出</div>
          <div className={Styles["rowDownMark-item"]}>行情</div>
        </section>
      );
    },
    clickHeight: 60,
  };

  return (
    <>
      <H5Table<dataType>
        disable
        column={column}
        tableData={data}
        onload={onload}
        pullDownProps={pullDownProps}
        changePullDownProps={changePullDownProps}
        handleHeadSortClick={handleHeadSortClick}
        clickOptions={clickOptions}
      ></H5Table>
    </>
  );
}

export default App;

// App.module.scss
.app {
  color: red;
  font-size: 20px;
  .container {
    color: aqua;
  }
}
.rowDownMark {
  width: 100%;
  display: flex;
  height: 60px;
  background-color: #fcfcfc;
  align-items: center;
}
.rowDownMark-item {
  flex-grow: 1;
  color: #309fea;
  text-align: center;
}

大数据量时 使用虚拟列表

相关props 说明

export type virtualTablePropsType<T = any> = {
  rowKey?: string; //表格行 key 的取值字段 默认取id字段
  minTableHeight?: number; //表格最小高度
  showRowNum?: number; // 表格显示几行
  headerHeight?: number; // 头部默认高度
  rowHeight?: number; //每行数据的默认高度
  column: Array<columnItemType<T>>;
  tableData: Array<T>;
  clickOptions?: clickOptions<T>; // 是否需要处理点击事件
  handleHeadSortClick?: (propsKey: string, type: sortStatusType) => void;
  rootValue?: number; //
};

// 0 默认 1 升 2 降
export type sortStatusType = 0 | 1 | 2;

export interface virtualTableInstance {
  scrollIntoView: (index: number) => void;
}

export type columnItemType<T = any> = {
  title: string; // 列名
  dataIndex: string; // table data key 值
  width: number; // 列 宽度
  sortable?: boolean; //是否 支持排序
  align?: "left" | "center" | "right"; // 布局
  render?: (item: T, index?: number) => any; //自定义单元格显示的内容
};

//  点击相关配置
export type clickOptions<T> = {
  clickRender: (item: T, index: number) => React.JSX.Element; // 点击列触发渲染
  clickHeight: number; // 显示栏的高度
};

代码示例:

// App.tsx
import { useRef, useState } from "react";
import {
  H5VirtualTable,
  clickOptions,
  columnItemType,
  sortStatusType,
  virtualTableInstance,
} from "@lqcoder/react-h5-table";

import Styles from "./App.module.scss";

function App() {
  type dataType = {
    id: number;
    type?: number;
    select: string;
    position: string;
    use: string;
    markValue: string;
    cur: string;
    cost: string;
    newPrice: number;
    float: string;
    profit: string;
    count: string;
  };
  const column: Array<columnItemType<dataType>> = [
    {
      title: "班费/总值",
      width: 250,
      dataIndex: "rateAndSum",
      render(item, _index) {
        return (
          <section className="nameAndMarkValue">
            <div className="name">
              {item.select}
              <span className="type">{item.type === 1 ? "深" : "沪"}</span>
            </div>
            <div className="markValue">
              {item.markValue}=={item.id}
            </div>
          </section>
        );
      },
      align: "left",
    },
    {
      title: "持仓/可用",
      dataIndex: "positionAndUse",
      sortable: true,
      width: 200,
      align: "right",
      render(item, _index) {
        return (
          <section className="positionAndUse">
            <div className="position">{item.position}</div>
            <div className="use">{item.use}</div>
          </section>
        );
      },
    },
    {
      title: "现价/成本",
      dataIndex: "curAndCost",
      sortable: true,
      width: 200,
      align: "right",
      render(item) {
        return (
          <section className="curAndCost">
            <div className="cur">{item.cur}</div>
            <div className="cost">{item.cost}</div>
          </section>
        );
      },
    },
    {
      title: "浮动/盈亏",
      dataIndex: "float",
      width: 200,
      align: "right",
      render(item) {
        return (
          <section className="floatAndProfit">
            <div className="float">{item.float}</div>
            <div className="profit">{item.profit}</div>
          </section>
        );
      },
    },
    {
      title: "账户资产",
      dataIndex: "count",
      width: 200,
    },
  ];

  const temp = Array.from({ length: 20000 }).map((item, index) => {
    return {
      id: index,
      select: "三年二班",
      type: 1,
      position: `${27000 + index * 10}`,
      use: "5,000",
      markValue: "500,033.341",
      cur: "30.004",
      cost: "32.453",
      newPrice: 20,
      float: "+18,879.09",
      profit: "-5.45%",
      count: "120,121",
    };
  });

  const dataRef = useRef(temp);
  const tableRef = useRef<virtualTableInstance>();

  const [num, setNum] = useState(1);
  const [data, setData] = useState(temp);

  /**
   * 处理排序按钮回调 处理逻辑交给开发
   * @param propsKey 点击的列名
   * @param type 0 默认 1 升 2 降
   * @returns
   */
  const handleHeadSortClick = (propsKey: string, type: sortStatusType) => {
    if (type === 0) {
      setData(dataRef.current);
      return;
    }
    if (propsKey === "positionAndUse") {
      if (type === 1) {
        const temp = [...dataRef.current].sort(
          (a, b) => Number(b.position) - Number(a.position)
        );
        setData(temp);
      } else {
        const temp = [...dataRef.current].sort(
          (a, b) => Number(a.position) - Number(b.position)
        );
        setData(temp);
      }
    }

    if (propsKey === "curAndCost") {
      if (type === 1) {
        const temp = [...dataRef.current].sort(
          (a, b) => Number(b.cur) - Number(a.cur)
        );
        setData(temp);
      } else {
        const temp = [...dataRef.current].sort(
          (a, b) => Number(a.cur) - Number(b.cur)
        );
        setData(temp);
      }
    }
  };

  const handelSell = () => {
    console.log("handelSell----");
  };

  const clickOptions: clickOptions<dataType> = {
    clickRender(item, index) {
      return (
        <section className={Styles["rowDownMark"]}>
          <div className={Styles["rowDownMark-item"]} onClick={handelSell}>
            买入
          </div>
          <div className={Styles["rowDownMark-item"]}>卖出</div>
          <div className={Styles["rowDownMark-item"]}>行情</div>
        </section>
      );
    },
    clickHeight: 60,
  };
  const scrollTo = () => {
    tableRef.current?.scrollIntoView(num);
  };

  const getValue = (val: any) => {
    setNum(Number(val.target.value) || 0);
  };

  return (
    <>
      <input type="text" onChange={getValue} />
      <button onClick={scrollTo}>跳到</button>
      <H5VirtualTable<dataType>
        disable
        column={column}
        tableData={data}
        handleHeadSortClick={handleHeadSortClick}
        clickOptions={clickOptions}
        ref={tableRef}
      ></H5VirtualTable>
    </>
  );
}

export default App;

// App.module.scss
.app {
  color: red;
  font-size: 20px;
  .container {
    color: aqua;
  }
}
.rowDownMark {
  width: 100%;
  display: flex;
  height: 60px;
  background-color: #fcfcfc;
  align-items: center;
}
.rowDownMark-item {
  flex-grow: 1;
  color: #309fea;
  text-align: center;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

聚类模型评估指标

聚类模型评估指标-轮廓系数 计算样本i到同簇其它样本到平均距离ai&#xff0c;ai越小&#xff0c;说明样本i越应该被聚类到该簇&#xff08;将ai称为样本i到簇内不相似度&#xff09;&#xff1b;计算样本i到其它某簇Cj的所有样本的平均距离bij&#xff0c;称为样本i与簇Cj的…

鉴源实验室|自动驾驶仿真测试技术分析

01 引言 随着科技的不断发展&#xff0c;自动驾驶技术逐渐成为汽车行业的热门话题。然而&#xff0c;要将自动驾驶车辆投放到真实道路上之前&#xff0c;必须进行广泛的测试&#xff0c;以确保其在各种情况下都能安全可靠地运行。自动驾驶车辆的测试是一个复杂而昂贵的过程。…

AQY212S光耦合器:特性和应用揭秘

在不断发展的电子元件领域&#xff0c;AQY212S光耦合器作为适合众多应用的多功能且可靠的解决方案脱颖而出。作为光耦合器技术专家&#xff0c;让我们深入研究AQY212S的功能和应用&#xff0c;揭开这款令人印象深刻的器件的神秘面纱。 AQY212S是一款固态继电器(SSR)光耦合器&a…

【docker-compose】【nginx】内网环境https配置

目录 1、openssl生成自签名证书和私钥2、nginx.conf配置ssl3、docker-compose挂载 1、openssl生成自签名证书和私钥 在部署服务器上&#xff0c;新建cert目录&#xff0c;执行以下指令&#xff0c;然后生成.crt和.key文件 openssl req -newkey rsa:2048 -nodes -keyout rsa_pri…

2023年全球软件架构师峰会(ArchSummit深圳站):核心内容与学习收获(附大会核心PPT下载)

本次峰会是一次重要的技术盛会&#xff0c;旨在为全球软件架构师提供一个交流和学习的平台。本次峰会聚焦于软件架构的最新趋势、最佳实践和技术创新&#xff0c;吸引了来自世界各地的软件架构师、技术专家和企业领袖。 在峰会中&#xff0c;与会者可以了解到数字化、AIGC、To…

指针定义与使用

系列文章目录 指针定义与使用 指针定义与使用 系列文章目录一、指针的定义与使用二、相关案例 一、指针的定义与使用 指针 指针的定义和使用&#xff1a; 1、指针&#xff1a;是一种数据类型 指针变量也是一种变量 int* p int*是数据类型 p是指针变量 2、指针格式&#xff1a;…

webpack面试题学习

说说你对webpack的理解&#xff1f;解决了什么问题&#xff1f; 说说webpack的构建流程? 说说webpack中常见的Loader&#xff1f;解决了什么问题&#xff1f; 说说webpack中常见的Plugin&#xff1f;解决了什么问题&#xff1f; 说说Loader和Plugin的区别&#xff1f;编写Load…

代码随想录 Leetcode459. 重复的子字符串(KMP算法)

题目&#xff1a; 代码&#xff08;首刷看解析 KMP算法 2024年1月18日&#xff09;&#xff1a; class Solution { public:void getNext(string& s,vector<int>& next) {int j 0;next[0] j;for (int i 1; i < s.size(); i) {while (j > 0 && s…

x-www-form-urlencoded接收方式代码示例

数据回推方式是 “x-www-form-urlencoded”&#xff0c;可以选择使用 GET 或 POST 方法来接收数据回推。 使用 GET 方法接收数据回推时&#xff0c;您可以将数据作为查询参数附加在请求的 URL 中。例如&#xff1a; http://example.com/callback?param1value1&param2val…

Redis高级系列-缓存双写一致性

Redis高级系列-缓存双写一致性 文章目录 Redis高级系列-缓存双写一致性1. 什么叫做缓存双写一致性&#xff1f;2. 缓存双写一致性有那些解决方案&#xff1f;2.1 Cache Aside Pattern(旁路缓存模式)延迟双删重试删除binlog订阅异步删除 2.2 Read Through/Write Through(读写穿透…

LightGlue: Local Feature Matching at Light Speed

一、论文概述 发表于&#xff1a; 2023 ICCV 作者信息&#xff1a;Philipp Lindenberger Paul-Edouard Sarlin Marc Pollefeys 对比算法&#xff1a;SuperGlue 代码&#xff1a;github.com/cvg/LightGlue 效果: 现有问题&#xff1a; 1&#xff09; SuperGlue 与其他基于 …

“尔滨”宠粉再升级!百亿像素VR冰雪盛宴

1月10日&#xff0c;由哈尔滨市委网信办、哈尔滨日报社主办&#xff0c;冰城客户端、哈尔滨新闻网承办的“激情迎亚冬&#xff0c;冰雪暖世界——2024年哈尔滨冰雪乐园”VR沉浸式体验产品正式上线。 如果你还没去过最近爆火出圈的“尔滨” ❄️这份哈尔滨冰雪景点VR❄️ 为你…

初识 Elasticsearch 应用知识,一文读懂 Elasticsearch 知识文集(4)

&#x1f3c6;作者简介&#xff0c;普修罗双战士&#xff0c;一直追求不断学习和成长&#xff0c;在技术的道路上持续探索和实践。 &#x1f3c6;多年互联网行业从业经验&#xff0c;历任核心研发工程师&#xff0c;项目技术负责人。 &#x1f389;欢迎 &#x1f44d;点赞✍评论…

HDClone X.5 新版功能亮点

在 HDClone X.4 版本的基础上,HDClone X.5 新版本推出了对网盘、映射磁盘等的镜像功能,让磁盘镜像更加如虎添翼。 创建卷的镜像:可将非物理介质作为卷,对其制作镜像,从而保护其中数据。挂载这些镜像后,即可直接访问其中的文件,设置的保护层可以确保文件不被更改。 用于存…

小程序系列--8.页面事件

一、下拉刷新事件 1. 什么是下拉刷新&#xff1f; 下拉刷新是移动端的专有名词&#xff0c;指的是通过手指在屏幕上的下拉滑动操作&#xff0c;从而重新加载页面数据的行为。 2. 启用下拉刷新 3. 配置下拉刷新窗口的样式 4. 监听页面的下拉刷新事件 在页面的 .js 文件中&am…

FastAPI 并发请求详解:提升性能的关键特性

在当今的数字化世界中&#xff0c;网络用户对于高速响应和持续连接的诉求日益显著。这促使了基于 Python 构建的 FastAPI 框架受到广泛关注&#xff0c;它不仅现代化且效率极高&#xff0c;而且简化了并行请求的处理。本篇文章旨在探讨 FastAPI 如何处理这类请求&#xff0c;并…

【遥感专题系列】影像信息提取之——面向对象的影像分类技术

“同物异谱&#xff0c;同谱异物”会对影像分类产生的影响&#xff0c;加上高分辨率影像的光谱信息不是很丰富&#xff0c;还有经常伴有光谱相互影响的现象&#xff0c;这对基于像素的分类方法提出了一种挑战&#xff0c;面向对象的影像分类技术可以一定程度减少上述影响。 本…

【AI接口】语音版、文心一言大模型和AI绘图、图片检测API

文章目录 一、语音版大模型AI1、接口2、请求参数3、请求参数示例4、接口返回示例 二、AI图片鉴黄合规检测API1、接口2、请求参数3、请求参数示例4、接口返回示例5、报错说明6、代码开源 三、人工智能AI绘画API1、接口2、请求参数3、请求参数示例4、接口返回示例5、AI绘画成果展…

Redis(四)

1、Redis的单/多线程 1.1、单线程 其实直接说Redis什么单线程或者是多线程&#xff0c;不太准确&#xff0c;在redis的4.0版主之前是单线程&#xff0c;然后在之后的版本中redis的渐渐改为多线程。 Redis是单线程主要是指Redis的网络IO和键值对读写是由一个线程来完成的&#…