首页IT科技uniapp 如何写pc页面(【移动端表格组件】uniapp简单实现H5,小程序,APP多端兼容表格功能,复制即用,简单易懂【详细注释版本】)

uniapp 如何写pc页面(【移动端表格组件】uniapp简单实现H5,小程序,APP多端兼容表格功能,复制即用,简单易懂【详细注释版本】)

时间2025-05-03 07:11:31分类IT科技浏览3914
导读:前言: 由于最近需要做移动端的项目...

前言:

由于最近需要做移动端的项目

有个pc端的后台系统里面需要移一部分页面过来

而里面就有很多的表格            ,我就开始惯例网上先找前人栽的树                 ,我好乘凉

然后找了一圈发现     ,不管是主流的移动端ui库或者网上自己写的帖子         ,或者uniapp的插件网站

都没有看到符合我要求的表格                  ,然后如果要改别人的源码那我看代码都要看很久        ,好切有些还奇奇怪怪的bug不兼容

可能是别人使用了某些组件和插件之类的           。导致我很多设置不生效                 。没错      ,我也改过别人的源码了                  ,后来放弃了      。

所以我就直接手写了一个简单的表格展示组件           ,配上一些我需要的功能         。可以先用着了                 。

重点是我是原生的标签写的   ,不是引入一大堆的插件之类的                  ,uniapp可以直接用         。

想修改源码也简单      。我都注释好了

效果图

小程序页面兼容              ,可以看到点击按钮之后会拿到对应行的数据

H5页面的,也是一样兼容的可能               ,也能拿到数据

移动端                 ,手机预览效果   ,展示了数据和点击生效            ,滚动到底部可以触发方法                 ,可以在这里写加载第二页表格的方法

功能:

1     ,数据展示:只需要往组件内传入表头和列表数据就能展示         ,列表数据和elementul的表格一样                 。表头要自己配置

2                  ,固定表头:上滚动的时候表头会定位在上面不动

3        ,固定列:表头内配置属性      ,可以让这一列固定左边不动            。目前只能固定一列

4                  ,行底纹:就是给一行的单元格加上背景色           ,需要在tabledata列表中添加一个字段bgcolor就可以了

5   ,列底纹:同上                  ,区别是在表头内添加一个字段bgcolor

6              ,单元格文字颜色改变:这是我们项目的要求,需要拿到每个单元格的数据和指标对比大小来标红   。这里在父组件就可以配置

7               ,操作列:表头添加操作列                 ,key给edit就会出现一个编辑和删除的列                 。不写就没有这一列               。点击按钮会触发父组件的方法

8   ,滚动到底部:滚动到底部会触发父组件方法。可以做业务操作            ,比如拿第二页的表格

9                 ,自动列宽:根据表格内单元格内容的宽度来动态赋值几个宽度     ,宽度是提前定义好的              。由于表头和表体需要宽度一致         ,所以提前设置几个档次的固定宽度                  。具体使用是自动根据表体或者表头哪一个长                  ,用哪一个的宽   。保证数据的展示完全           。当数据过长的时候会自动隐藏并省略号显示                 。这里我就没有加其他的功能了        ,后期可以自行更改      ,把这个文字加一个组件包裹                  ,就是点击可以显示全部文字的弹框那个      。

引入组件

uniapp可以直接使用           ,整体就引入了一个组件   ,uniapp带有的scroll-view组件         。需要去uniapp文档内引入一下                  ,直接插件市场下载一下就好了

代码:

组件部分:

写一个tableDiv的vue文件              ,当然名字随便你换

然后把代码复制进去                 。 <template> <view class="wrap"> <!-- @scrolltolower:滚动到底部触发 lower-threshold:距离底部多少距离触发@scrolltolower --> <scroll-view class="scroll-view_H" scroll-x="true" scroll-y="true" @scrolltolower=scrollBottom :lower-threshold=2> <view class="top" id="top" :style="{width:tableWidths+px}"> <view v-for="(h,n) in header" :key=n :class="{header_dyg:true,flexs:h.flxe}" :style="{width:h.hWidth+px}"> {{h.name}} </view> </view> <view class="bottom" :style="{maxHeight: tableHeight+px,width:tableWidths+px}"> <view class="tablebox" v-for="(t,s) in tableData" :key=s @click="jumpDetailed(t)"> <view v-for="(h,n) in header" :key="n" :class="{table_dyg:true,tdColClass:h.bgcolor,tdRowClass:t.bgcolor,flexs:h.flxe}" :style="{width:h.hWidth+px}"> <!-- 不等于操作列就显示文字 --> <text v-if="h.key!==edit" :style="{color:getColor(t,h)}">{{t[h.key]}}</text> <!-- 操作列显示按钮,后期用插槽 --> <view class="uni-group" v-else style="background-color: #fff;"> <button class="uni-button" size="mini" type="primary" style="margin-right: 5px;" @click="editTable(t)">编辑</button> <button class="uni-button" size="mini" type="warn" @click="deleteTable(t)">删除</button> </view> </view> </view> </view> </scroll-view> </view> </template> <script> // 表头配置:flxe(固定列)               ,bgcolor(列底纹) // 表体配置:bgcolor(行底纹) export default { props: { data2: { type: Array, required: true, default: function() { return []; } }, head: { type: Array, required: true, default: function() { return []; } }, tableHeight: { required: true, type: [Number, String], default: function() { return 0; } } }, data() { return { //表体 tableData: [], //表头 header: [], // 表格总长度 tableWidths:0 } }, watch:{ // 监听列表 data2(a,b){ this.tableData = a }, // 监听表头 head(a,b){ this.header = a //计算列宽 this.tableWidth() }, }, created() { //#ifdef H5 this.tableData = this.data2 //列表 this.header = this.head //表头 this.tableWidth() // #endif }, methods: { // 返回行数据 jumpDetailed(row){ this.$emit(rowData,row) }, // 滚动到底部                 ,调用父组件方法 scrollBottom(e) { // 滚动到底部才触发   ,滚动到右边不触发 if (e.detail.direction == "bottom") { this.$emit(scrollBottom) } }, // 颜色对比 getColor(row, col) { let color = black // 传值给父组件            ,通过父组件的方法内计算判断当前单元格数据是否需要标红                 ,然后通过回调函数     ,返回一个color值来渲染 this.$emit(getTextColor, row, col, val => { color = val }) return color }, // 修改按钮 editTable(val) { this.$emit(getEdit, val) }, // 删除按钮 deleteTable(val) { this.$emit(getDelete, val) }, // 计算单元格宽度 tableWidth() { let w=0 //计算表格长度 this.header.forEach((head, index) => { let hw = head.name.length //表头单元格宽度 let dw = 0 //列表单元格宽度 this.tableData.forEach(data => { // 如果是操作列         ,就直接给十个字符长度                  ,也就是列宽自动150        ,不是操作列的统一看字符串长度决定宽度 let a = (head.key == edit ? 1234567891 : (data[head.key]?data[head.key].toString():1)) let tw = (head.key == edit ? 10 : a.length) // 这里每次循环找出更大的数赋值      ,确保dw中是表体单元格这一列中最大宽度                  ,根据最大宽度来判断单元格显示 if (dw < tw) { dw = tw } }) // 表体单元格内容宽度小于表头内容时           ,以表头的宽度为主         。根据表头的字符长度来区分宽度 if (dw <= hw) { if (hw <= 3) { head[hWidth] = 50 } else if (hw <= 5) { head[hWidth] = 80 } else { head[hWidth] = 130 } } else { // 表体内容宽度大于表头内容宽度时   ,以表体宽度为主      。根据表头的字符长度来区分宽度 if (dw <= 3) { head[hWidth] = 50 } else if (dw <= 5) { head[hWidth] = 80 } else { head[hWidth] = 130 } } w+=head[hWidth] //叠加表格总长度 }) this.tableWidths=w //给表格赋值总长度 } } } </script> <style lang="scss"> .wrap { width: 100%; } // 表头 .top { display: flex; position: sticky; //表头向上滚动时固定住 top: 0; //width: 750px; //左右滚动时不会把固定的表头滚动走 z-index: 100; //滑动时表头不被覆盖 .header_dyg { height: 40px; text-align: center; line-height: 40px; border-top: 1px solid #ccc; border-right: 1px solid #ccc; border-bottom: 1px solid #ccc; padding: 0 5px; background-color: #f5f5f6; font-size: 14px; font-weight: bold; color: #2b2b2b; flex-shrink: 0; } // 列定位固定单元格 .flexs { position: sticky; left: 0; background-color: #f5f5f6; z-index: 10; } } // 表格列表 .bottom { //width: 750px; .tablebox { display: flex; font-size: 14px; .table_dyg { height: 30px; text-align: center; line-height: 30px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; border-right: 1px solid #ccc; border-bottom: 1px solid #ccc; padding: 0 5px; flex-shrink: 0; } // 列定位固定单元格 .flexs { position: sticky; left: 0; background-color: #fff; z-index: 10; } } } // 列的颜色 .tdColClass { background-color: #d9edf7; } // 行的颜色 .tdRowClass { background-color: #afdfe4; } </style>

然后父组件引入子组件使用

<template> <view class="box"> <!-- 表格组件:参数解释:@getTextColor:调用方法判断数据后返回对比颜色                  ,可以改变单元格文字的颜色 --> <!-- @getEdit:点击表格中编辑按钮会触发的方法 @getDelete:点击表格中删除按钮会触发的方法 @scrollBottom:滚动到底部时触发 @rowData:获取点击行的数据--> <!-- data:列表数据              ,格式和elementul表格一样,head:表头数据               ,格式[{name:列名,key:对应列表的key,bgcolor:1代表这一列添加背景色,flxe:1代表这一列固定}],tableHeight:表格表体高度 --> <mytable @scrollBottom=scrollBottom @getTextColor=getRedText @getEdit=editTable @getDelete=deleteTable @rowData=getRow :data2=tableData :head=header :tableHeight=310> </mytable> </view> </template> <script> import tableDiv from ./tableDiv.vue export default { components: { tableDiv }, data() { return { //表体 tableData: [{ "date": "2020-09-01", "name": "11", "address": "上海市普陀区金沙江路 1518 弄", "age": "18", bgcolor: 1 }, { "date": "2020-09-02", "name": "22", "address": "上海市普陀区金沙江路 1517 弄", "age": "18" }, { "date": "2020-09-03", "name": "33", "address": "上海市普陀区金沙江路 1519 弄", "age": "18" }, { "date": "2020-09-04", "name": "44", "address": "上海市普陀区金沙江路 1516 弄", "age": "18" }, { "date": "2020-09-05", "name": "55", "address": "上海市普陀区金沙江路 1518 弄", "age": "18" }, { "date": "2020-09-06", "name": "66", "address": "上海市普陀区金沙江路 1517 弄", "age": "18" }, { "date": "2020-09-06", "name": "66", "address": "上海市普陀区金沙江路 1517 弄", "age": "18" }, { "date": "2020-09-06", "name": "66", "address": "上海市普陀区金沙江路 1517 弄", "age": "18" }, { "date": "2020-09-06", "name": "66", "address": "上海市普陀区金沙江路 1517 弄", "age": "18" }, { "date": "2020-09-06", "name": "66", "address": "上海市普陀区金沙江路 1517 弄", "age": "18" }, { "date": "2020-09-06", "name": "66", "address": "上海市普陀区金沙江路 1517 弄", "age": "18" }, { "date": "2020-09-06", "name": "66", "address": "上海市普陀区金沙江路 1517 弄", "age": "18" }, { "date": "2020-09-06", "name": "66", "address": "上海市普陀区金沙江路 1517 弄", "age": "18" }], //表头 header: [{ name: 日期, key: date, flxe: 1 //固定的列                 ,只能有一个列 }, { name: 姓名, key: name, bgcolor: 1 //列底纹 }, { name: 地址, key: address }, { name: 年龄, key: age }, { name: 年龄, key: age }, { name: 操作, key: edit }] } }, methods: { // 自定义事件方法   ,业务逻辑判断是否需要标红            ,然后回调给子组件颜色 getRedText(row, col, callback) { let color = black // 判断值是否需要标红 if (row[col.key] == 22) { color = red } else { color = black } // 通过回调函数返回值 callback(color); }, // 编辑按钮 editTable(val){ console.log(val,编辑); uni.showToast({ title: val.date+编辑 }) }, // 删除按钮 deleteTable(val){ console.log(val,删除); uni.showToast({ title: val.date+删除 }) }, // 滚动到底部 scrollBottom(){ uni.showToast({ title: 滚动到底部了 }) console.log(滚动到底部了); } } } </script> <style lang="scss"> </style>

注意点:

由于小程序不支持直接vue那种父子组件传参形式                 。拿不到数据                 ,所以这里需要用watch监听一下props变化及时更新子组件            。

H5页面是可以支持vue的原本写法的   。直接进来拿props就可以使用了                 。所以这里直接created内赋值一下就可以了

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
SEO优化指南(提高网站排名的实践方法) python把字典写入txt文件(python如何将字典内容写入json文件)