vue3-h5-table
介绍
适用于 vue3 + ts 的 h5 移动端项目 table 组件
支持 左侧固定 滑动 每行点击回调 支持 指定列排序
链接 :https://github.com/duKD/vue3-h5-table
效果
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<columnItemType>; tableDatas: Array<any>; isClick?: boolean; // 是否需要触发行点击事件 disable?: boolean; // 是否启用下拉加载 error?: boolean; // 数据加载失败 loading?: boolean; // 数据处于加载状态 finish?: boolean; // 数据 是否完全加载 loadingText?: string; // 加载文案 errorText?: string; // 失败文案 finishedText?: string; // 完成文案 offset?: number; //触发加载的底部距离 rootValue?: number; // };
复制
使用 实例:
<template> <div class="position"> <section style="height: 200px"></section> <h5-table ref="h5TableRef" :column="column" :table-datas="tableDatas" @row-click="rowClick" @handle-head-sort-click="handleHeadSortClick" v-model:error="error" :is-click="true" v-model:loading="loading" :finish="finish" @load="onload" > <template #titleSlot> <section class="nameAndMarkValueTitle"> <div> <span class="name_1"> 班费 </span>/<span class="name_2"> 总和 </span> </div> </section> </template> <template #title="item"> <section class="nameAndMarkValue"> <div class="name"> {{ item.select }} <span class="type">{{ item.type === 1 ? "深" : "沪" }}</span> </div> <div class="markValue">{{ item.markValue }}=={{ item.id }}</div> </section> </template> <template #positionAndUse="item"> <section class="positionAndUse"> <div class="position"> {{ item.position }} </div> <div class="use">{{ item.use }}</div> </section> </template> <template #curAndCost="item"> <section class="curAndCost"> <div class="cur"> {{ item.cur }} </div> <div class="cost">{{ item.cost }}</div> </section> </template> <template #floatAndProfit="item"> <section class="floatAndProfit"> <div class="float">{{ item.float }}</div> <div class="profit">{{ item.profit }}</div> </section> </template> <template #rowDownMark> <section class="rowDownMark"> <div class="rowDownMark-item" @click="handelSell">买入</div> <div class="rowDownMark-item">卖出</div> <div class="rowDownMark-item">行情</div> </section> </template> </h5-table> </div> </template> <script setup lang="ts"> import { H5Table } from "../lib/h5-table"; import type { columnItemType, sortStatusType } from "../lib/h5-table/types"; import { ref, watch } from "vue"; const column: Array<columnItemType> = [ { 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<Array<any>>(JSON.parse(JSON.stringify(temp))); const h5TableRef = ref<typeof H5Table | null>(null); const loading = ref<boolean>(false); const error = ref<boolean>(false); const finish = ref<boolean>(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===="); }; </script> <style> body { padding: 0; margin: 0 !important; } </style> <style lang="scss" scoped> .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; } } } </style>
复制
具体使用参考 github 项目中 app.vue 文件
更新日志
2023.9.27
- 修改transform 渲染方式 不经过 vue 派发更新(数据量过大 会有卡顿),直接用原生js 去控制
具体表现如下图(1000条列表数据)
在左右滑动1s内 有300多ms 消耗到 vue3 的派发更新上,但是我们人为是知道只有组件样式需要改变,所以可以考虑优化 ,将更新的操作用原声js 实现 ,不走vue 响应更新
vue派发更新时间就省略了,响应速度提高了200多ms。就基本不会卡顿了
- 增加 rootValue 配置 默认75(基于rootValue 去将 props 中的 一些 长度单位 传化成 rem) 修复pad 样式问题(保持和 postCssPxToRem 插件配置一致 )
postCssPxToRem({
// 自适应,px>rem转换
rootValue: 75, // 75表示750设计稿,37.5表示375设计稿
propList: [“*”], // 需要转换的属性,这里选择全部都进行转换
selectorBlackList: [“norem”], // 过滤掉norem-开头的class,不进行rem转换
}), - 优化一些参数命名
- 将点击 显示操作栏目的操作 更多内置化,便于使用
2023.10.7
处理了 屏幕尺寸变化(一般生产环境 用户屏幕尺寸不会发生变化) 引发一些问题
2023.10.10
表头 固定优化 处理ios fixed 滑动问题
2023.10.20
cell组件 改为函数组件 加快渲染速度
2023.10.31
解决cloumn修改宽带导致表格宽度改变引发的空白问题
2024.1.8
修复滚动过快 无法触发load事件问题