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

这篇具有很好参考价值的文章主要介绍了一个 适用 vue3 ts h5移动端 table组件。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

vue3-h5-table

介绍

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

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

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

效果

vue3-h5-table,前端,开发语言,typescript

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

  1. 修改transform 渲染方式 不经过 vue 派发更新(数据量过大 会有卡顿),直接用原生js 去控制
    具体表现如下图(1000条列表数据)
    vue3-h5-table,前端,开发语言,typescript
    在左右滑动1s内 有300多ms 消耗到 vue3 的派发更新上,但是我们人为是知道只有组件样式需要改变,所以可以考虑优化 ,将更新的操作用原声js 实现 ,不走vue 响应更新

vue3-h5-table,前端,开发语言,typescript

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事件问题文章来源地址https://www.toymoban.com/news/detail-765373.html

到了这里,关于一个 适用 vue3 ts h5移动端 table组件的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • VUE3+TS(父子、兄弟组件通信)

    目录 父传子值、方法(子调用父值、方法) 子传父值(父调用子值) 父读子(子传父)(父调用子值、方法) 兄弟(任意组件)通信 引入Mitt来完成任意组件通信 1、统一规范写法,通过在子组件标签上绑定属性和值,来传递到子组件,子组件再通过defineProps来接收,先给其

    2023年04月08日
    浏览(36)
  • vue3+Ts 开发H5项目在线浏览pdf/word/pptx/xlsx文件方法分享

    pdf需要pdfh5这个插件才可以在线浏览,所以我们先下载插件; pdfh5官方地址 注意 “pdfh5”: “^1.4.7” 有问题会出现插件不能完全加载出现504错误 请切换版本下载 “pdfh5”: \\\"^1.4.2\\\"版本 其实很简单 就只用处理一下pdf类型的文件就可以了 其他文件 office 有一个自带的线上网站可以拼

    2024年02月16日
    浏览(43)
  • Vue3 TS写法 父子组件传值(通讯)

    父组件: 子组件: 通过defineProps来接受数据(无须引入直接使用即可) 子组件可写默认值也可以不写两种情况 子组件通过defineEmits派发一个事件 (一样无须引入直接使用即可)  父组件接受子组件的事件 chilFun

    2024年02月15日
    浏览(29)
  • vue3 ts获取组件 ref元素的值

    在 Vue 3 + TypeScript 中,要获取组件 ref 元素的值,可以通过 ref 函数创建一个 ref,并将其绑定到组件的 ref 属性上。然后,可以通过访问 ref 的 .value 属性来获取该组件的实例。 以下是一个示例代码: 在上述代码中,我们首先使用 ref 函数创建了一个名为 childComponentRef 的 ref,并

    2024年02月05日
    浏览(36)
  • vue3+ts+vite项目引入echarts,vue3项目echarts组件封装

    技术栈 :Vue3 + Ts + Vite + Echarts 简介 : 图文详解,教你如何在 Vue3 项目中 引入Echarts , 封装Echarts组件 ,并实现常用Echarts图例 1.1 静态效果 1.2 动态效果 2.1 安装 Echarts npm: pnpm: 2.2 main.ts 中引入 2.3 Echarts 组件封装 /src/components/ReEcharts/index.vue 文件中写入如下代码 3.1 柱状图 实现

    2024年02月09日
    浏览(46)
  • 基于Vant组件库二次封装组件(TS+Vue3.x环境)

    1. 今天的需求是封装一个 Navigation Bar 导航栏组件,目的是给到App几乎所有的页面复用:      2. 因为之前的项目里使用过Vant组件库,笔者第一时间想到了Vant组件库中的 NavBar 组件,和当前App的需求匹配度很高。Vant组件库的 NavBar 组件: 3. 相信你也发现了,Vant组件库默认主题

    2023年04月18日
    浏览(32)
  • Vue3Ts中如何实现父组件传递给子组件

            最开始我写vue3项目的时候父子组件传递数据,我直接按钮scope.row传递,子组件接收的时候为init接收,但是这种情况出现了一个情况就是当你点击弹窗的时候,明明数据已经给你传送接收了,断点查数据也没有问题,就是出现一个渲染有时候停留在上一个页面的bug。

    2024年01月21日
    浏览(30)
  • 中国省市区地区选择组件(ElementPlus + Vue3 + TS )

    1.引用 2.用法 provinceAndCityData :省市数据(不带“全部”选项) regionData :省市区数据(不带“全部”选项) provinceAndCityDataPlus :省市区数据(带“全部”选项) regionDataPlus :省市区数据(带“全部”选项) CodeToText :例如:CodeToText[‘110000’]输出北京市 TextToCode :例如:

    2023年04月27日
    浏览(52)
  • Vue3通透教程【十八】TS为组件的props标注类型

    专栏介绍: 凉哥作为 Vue 的忠实 粉丝输出过大量的 Vue 文章,应粉丝要求开始更新 Vue3 的相关技术文章,Vue 框架目前的地位大家应该都晓得,所谓三大框架使用人数最多,公司选型最多的框架,凉哥之前在文章中也提到过就是 Vue 框架之所以火起来的原因,和 Vue 框架相比其

    2024年02月16日
    浏览(27)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包