一个 适用 vue3 ts h5移动端 table组件

2024-06-04 9786阅读

vue3-h5-table

介绍

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

支持 左侧固定 滑动 每行点击回调 支持 指定列排序

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

效果

一个 适用 vue3 ts h5移动端 table组件 第1张

props说明
minTableHeight表格最小高度 可选 默认600
rowNum表格显示几行 可选 默认 6
headerHeight头部默认高度 可选 默认 60
rowHeight每行数据的默认高度 默认 100
column每列数据说明 见下文
tableDatas表格数据
fixedHeader是否固定表头 默认true
export type columnItemType = {
   title:string // 列名
   dataIndex?:string // table data key 值 
   width?:number // 列 宽度
   slotKey?:string // 插槽作用域 id
   sortable?:boolean //是否 支持排序
   align?: 'left'|'center'|'right' // 布局
   key?:string // 哪个列数据 作为 唯一key 值 默认 index
   render?:(h:renderType,row:any)=>void // 自定义render
   
}
type propsType = {
  minTableHeight?: number; //表格最小高度
  rowNum?: number; // 表格显示几行
  headerHeight?: number; // 头部默认高度
  rowHeight?: number; //每行数据的默认高度
  column: Array;
  tableDatas: Array;
  isClick?: boolean; // 是否需要触发行点击事件
  disable?: boolean; // 是否启用下拉加载
  error?: boolean; // 数据加载失败
  loading?: boolean; // 数据处于加载状态
  finish?: boolean; // 数据 是否完全加载
  loadingText?: string; // 加载文案
  errorText?: string; // 失败文案
  finishedText?: string; // 完成文案
  offset?: number; //触发加载的底部距离
  rootValue?: number; //  
};

使用 实例:

  
班费 / 总和
{{ item.select }} {{ item.type === 1 ? "深" : "沪" }}
{{ item.markValue }}=={{ item.id }}
{{ item.position }}
{{ item.use }}
{{ item.cur }}
{{ item.cost }}
{{ item.float }}
{{ item.profit }}
买入
卖出
行情
import { H5Table } from "../lib/h5-table"; import type { columnItemType, sortStatusType } from "../lib/h5-table/types"; import { ref, watch } from "vue"; const column: Array = [ { title: "班费/总值", key: "id", dataIndex: "nameAndMarkValue", width: 250, slotKey: "title", slotTitleKey: "titleSlot", align: "left", }, { title: "持仓/可用", slotKey: "positionAndUse", dataIndex: "positionAndUse", sortable: true, width: 200, align: "right", }, { title: "现价/成本", slotKey: "curAndCost", dataIndex: "curAndCost", // sortable: true, width: 200, align: "right", }, { title: "浮动/盈亏", width: 200, slotKey: "floatAndProfit", align: "right", }, { title: "账户资产", dataIndex: "count", width: 200, }, ]; const datas = [ { id: 0, select: "三年二班", type: 1, position: "27000", 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", }, { id: 1, select: "四年一班", type: 1, markValue: "23,933.341", position: "28000", use: "5,000", newPrice: 20, cur: "30.004", cost: "32.453", float: "+18,879.09", profit: "-5.45%", count: "120,121", }, { id: 2, select: "三年二班", markValue: "500,033,341", newPrice: 20, cur: "30.004", cost: "32.453", position: "27300", use: "5,000", float: "+18,879.09", profit: "-5.45%", count: "120,121", }, { id: 3, select: "五年二班", markValue: "500,033,341", position: "27000", use: "5,000", cur: "30.004", cost: "32.453", newPrice: 20, float: "+18,879.09", profit: "-5.45%", count: "120,121", }, { id: 4, select: "一年二班", markValue: "500,033,341", position: "27000", use: "5,000", newPrice: 20, cur: "30.004", cost: "32.453", float: "+18,879.09", profit: "-5.45%", count: "120,121", }, { id: 5, select: "六年三班", markValue: "500,033,341", position: "37000", use: "5,000", newPrice: 20, cur: "30.004", cost: "32.453", float: "+18,879.09", profit: "-5.45%", count: "120,121", }, { id: 6, select: "六年二班", markValue: "500,033,341", position: "37000", use: "5,000", newPrice: 20, cur: "30.004", cost: "32.453", float: "+18,879.09", profit: "-5.45%", count: "120,121", }, { id: 7, select: "六年五班", markValue: "500,033,341", position: "37000", use: "5,000", newPrice: 20, cur: "30.004", cost: "32.453", float: "+18,879.09", profit: "-5.45%", count: "120,121", }, ]; const temp = Array.from({ length: 300 }).map((item, index) => { return { id: index, select: "三年二班", type: 1, position: "27000", 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 tableDatas = ref(JSON.parse(JSON.stringify(temp))); const h5TableRef = ref(null); const loading = ref(false); const error = ref(false); const finish = ref(false); const onload = () => { console.log("loading===="); setTimeout(() => { tableDatas.value = tableDatas.value.concat( Array.from({ length: 100 }).map((item, index) => { return { id: new Date().getTime() + index, select: "三年二班", type: 1, position: "27000", 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", }; }) ); loading.value = false; }, 1000); // setTimeout(() => { // error.value = true; // }, 1000); // setTimeout(() => { // finish.value = true; // }, 1000); }; const rowClick = (item: any, index: number) => { if (h5TableRef.value) { //第一个参数 即是 设计稿 插槽的高度 h5TableRef.value.handleDom(60, index); } }; //处理排序 const handleHeadSortClick = (propsKey: string, type: sortStatusType) => { if (type === 0) { tableDatas.value.splice(0, tableDatas.value.length, ...datas); return; } if (propsKey === "positionAndUse") { if (type === 1) { tableDatas.value.sort((a, b) => Number(b.position) - Number(a.position)); } else { tableDatas.value.sort((a, b) => Number(a.position) - Number(b.position)); } } }; watch(tableDatas.value, () => { console.log("watch====", tableDatas); }); const handelSell = () => { console.log("handelSell===="); }; body { padding: 0; margin: 0 !important; } .position { font-size: 24px; .nameAndMarkValueTitle { display: flex; } .nameAndMarkValue { padding: 10px; .name { display: inline-block; position: relative; color: #222; font-size: 32px; .type { position: absolute; top: 50%; transform: translateY(-50%); right: -40px; display: inline-block; font-size: 24px; border: 1px solid #ff858d; padding: 0 4px; color: #ff858d; } } .markValue { color: #999; font-size: 24px; } } .positionAndUse { font-size: 28px; .position { color: #222; } .use { color: #999; } } .curAndCost { font-size: 28px; .cur { color: #222; } .cost { color: #999; } } .floatAndProfit { color: red; } .rowDownMark { width: 100%; display: flex; height: 60px; background-color: #fcfcfc; align-items: center; .rowDownMark-item { flex-grow: 1; color: #309fea; text-align: center; } } }

具体使用参考 github 项目中 app.vue 文件

更新日志

2023.9.27

  1. 修改transform 渲染方式 不经过 vue 派发更新(数据量过大 会有卡顿),直接用原生js 去控制

    具体表现如下图(1000条列表数据)

    一个 适用 vue3 ts h5移动端 table组件 第2张

    在左右滑动1s内 有300多ms 消耗到 vue3 的派发更新上,但是我们人为是知道只有组件样式需要改变,所以可以考虑优化 ,将更新的操作用原声js 实现 ,不走vue 响应更新

一个 适用 vue3 ts h5移动端 table组件 第3张

vue派发更新时间就省略了,响应速度提高了200多ms。就基本不会卡顿了

  1. 增加 rootValue 配置 默认75(基于rootValue 去将 props 中的 一些 长度单位 传化成 rem) 修复pad 样式问题(保持和 postCssPxToRem 插件配置一致 )

    postCssPxToRem({

    // 自适应,px>rem转换

    rootValue: 75, // 75表示750设计稿,37.5表示375设计稿

    propList: [“*”], // 需要转换的属性,这里选择全部都进行转换

    selectorBlackList: [“norem”], // 过滤掉norem-开头的class,不进行rem转换

    }),

  2. 优化一些参数命名
  3. 将点击 显示操作栏目的操作 更多内置化,便于使用

2023.10.7

处理了 屏幕尺寸变化(一般生产环境 用户屏幕尺寸不会发生变化) 引发一些问题

2023.10.10

表头 固定优化 处理ios fixed 滑动问题

2023.10.20

cell组件 改为函数组件 加快渲染速度

2023.10.31

解决cloumn修改宽带导致表格宽度改变引发的空白问题

2024.1.8

修复滚动过快 无法触发load事件问题


    免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

    目录[+]