微信小程序多人编辑表格(微信小程序实现固定表头、列表格组件)
类别:编程学习 浏览量:261
时间:2021-10-16 00:17:14 微信小程序多人编辑表格
微信小程序实现固定表头、列表格组件目录
- 需求:
- 功能点
- 效果图
- 实现思路
- 具体代码(react\taro3.0)
- 具体代码(小程序原生)
- 总结
微信小程序实现固定表头固定列表格组件(移动端做点小修改通用)
功能点- 排序表格
- 表头可固定
- 首列固定(可以优化成可以配置指定列左侧右侧固定)
- 翻页(上拉加载)监听
开始想用三个ScrollView去实现滚动联动,固定表头、列的话,表格内容滚动表头、列也应该对应滚动,写了demo后发现监听一个ScrollView的位置信息去设置另外两个ScrollView的位置真机会很卡,体验极差
使用position:sticky; 让表头相对表格顶部sticky,每行的第一个元素相对当前行左侧sticky。
遇到的问题:
- 表格左滑的时候,滑动一个屏幕后固定列跟着滑出屏幕了。解决方法:动态设置表格的宽度,原理:滑出去的原因是整行滑出屏幕了,而sticky是相对整行左侧定位的。
- 表格高度设置为100%后useReachBottom上拉监听失效 将表格高度设高的话固定表头就失效了。解决方法:表格用ScrollView套一层使用onScrollToLower监听加载
index.tsx
/** * 可滑动、固定表头、固定列表格组件 * @example <Table data={data} dataAttribute={dataAttribute} sortTypeChange={sortTypeChange} handleRow={toDetails}/> */ import React, { useState, useMemo, useEffect } from 'react' import classNames from 'classnames' // components import { View, Text, ScrollView } from '@tarojs/components' // utils import { noop } from '@/utils/util' // styles import styles from './index.module.less' interface DataAttributeItem { title: string key: string | number sortKey?: string | number } interface Props { data: Array<any> dataAttribute: Array<DataAttributeItem> sortTypeChange?: (sort_item_id: any, sort_desc: boolean) => void handleRow?: (data: any) => void handleScrollToLower?: (e: any) => void } export default function Table(props: Props) { const { data, dataAttribute, sortTypeChange = noop, handleRow = noop, handleScrollToLower = noop } = props const [isSortDesc, setIsSortDesc] = useState<boolean>(true) const [sortIndex, setSortIndex] = useState<number>(1) const tableWidth = useMemo(() => { return `${(dataAttribute.length * 148 + 48)}rpx` }, [dataAttribute]) const tableHeight = useMemo(() => { return `${((data.length + 1) * 96)}rpx` }, [data]) const handleSortItem = (attrItem, attrIndex) => { if (attrIndex === 0) { return } const beforeIndex = sortIndex const sortKey = attrItem.sortKey dataAttribute.map((item, index)=>{ if (item.sortKey === sortKey) { if (beforeIndex === index) { setIsSortDesc(!isSortDesc) } else { setSortIndex(index) setIsSortDesc(true) } } }) } useEffect(()=>{ const sort_desc = isSortDesc const sort_item_id = dataAttribute[sortIndex].sortKey sortTypeChange(sort_item_id,sort_desc) },[sortIndex, isSortDesc]) return ( <ScrollView className={styles['table']} scrollY scrollX onScrollToLower={handleScrollToLower}> <View className={styles['sticky-box']} style={{height: tableHeight}}> <View className={styles['grey-box']} style={{width: tableWidth, position: 'sticky'}}/> <View className={styles['table__head']} style={{width: tableWidth, position: 'sticky'}}> {dataAttribute.map((attrItem, attrIndex) => ( <View className={styles['table__head__td']} key={attrIndex} onClick={()=>handleSortItem(attrItem, attrIndex)}> <Text className={classNames({ [styles['table__head__td__text']]: true, [styles['table__head__td__text-active']]: sortIndex === attrIndex, })} key={attrIndex} >{attrItem.title}</Text> {attrIndex !== 0 && <View className={classNames({ [styles['table__head__td__sorter-indicate']]: true, [styles['table__head__td__sorter-indicate--asc-active']]: sortIndex === attrIndex && !isSortDesc, [styles['table__head__td__sorter-indicate--desc-active']]: sortIndex === attrIndex && isSortDesc })} />} </View> ))} </View> {data.map((dataItem, dataIndex) => ( <View className={styles['table__row']} key={dataIndex} style={{width: tableWidth}} onClick={() => handleRow(dataItem)}> {dataAttribute.map((attrItem, attrIndex) => { return ( <Text className={styles['table__row__td']} key={attrIndex}>{dataItem[attrItem.key] || '-'}</Text> ) })} </View> ))} </View> </ScrollView> ) }
index.module.less
@import '~@/assets/style/mixins/ellipsis.less'; page{ font-size: 26rpx; line-height: 60rpx; color: #222; height: 100%; width: 100%; } .grey-box{ height: 10rpx; top: 0; background: #f8f8f8; z-index: 100; } .table{ position: relative; overflow: scroll; width: 100%; height: 100%; overflow: scroll; &__head{ position: relative; height: 96rpx; white-space: nowrap; // position: sticky; top: 10rpx; z-index: 100; height: 88rpx; font-size: 24rpx; line-height: 88rpx; color: #aaabbd; background-color: #f8f8f8; border-bottom: 2rpx solid #ecf1f8; background-color: #fff; white-space: nowrap; display: flex; &__td{ .ellipsis(); width: 148rpx; // padding-right: 40rpx; display: flex; justify-content: flex-start; align-items: center; background-color: #fff; position: relative; box-sizing: border-box; &:nth-child(1) { padding-left: 24rpx; width: 154rpx; margin-right: 40rpx; position: sticky; z-index: 10; left: 0; } &__text{ display: inline; &-active{ color: #6d70ff; } } &__sorter-indicate{ width: 24rpx; height: 24rpx; display: inline-block; background-repeat: no-repeat; background-size: 100% 100%; background-image: url('https://icon1.jpg" alt="微信小程序多人编辑表格(微信小程序实现固定表头、列表格组件)" border="0" />
<ScrollView class="table" scroll-x scroll-y bindscrolltolower="handleScrollToLower"> <View class="sticky-box" style="height:{{tableHeight}}rpx;"> <View class="table__head" style="width:{{tableWidth}}rpx;"> <View class="table__head__td" wx:for="{{dataAttribute}}" wx:key="attrIndex" wx:for-index="attrIndex" wx:for-item="attrItem"> <Text class="table__head__td__text" >{{attrItem.title}}</Text> </View> </View> <View class="table__row" wx:for="{{data}}" wx:key="dataIndex" wx:for-index="dataIndex" wx:for-item="dataItem" style="width:{{tableWidth}}rpx;"> <Text class="table__row__td" wx:for="{{dataAttribute}}" wx:key="dataIndex" wx:for-index="attrIndex" wx:for-item="attrItem">{{dataItem[attrItem.key] || '-'}}</Text> </View> </View> </ScrollView>
const app = getApp() Page({ data: { data: [ { a: 123, b: 456, c: 489, d: 789, e: 458, f: 789 }, { a: 123, b: 456, c: 489, d: 789, e: 458, f: 789 }, { a: 123, b: 456, c: 489, d: 789, e: 458, f: 789 }, { a: 123, b: 456, c: 489, d: 789, e: 458, f: 789 }, { a: 123, b: 456, c: 489, d: 789, e: 458, f: 789 }, { a: 123, b: 456, c: 489, d: 789, e: 458, f: 789 }, { a: 123, b: 456, c: 489, d: 789, e: 458, f: 789 }, { a: 123, b: 456, c: 489, d: 789, e: 458, f: 789 }, { a: 123, b: 456, c: 489, d: 789, e: 458, f: 789 }, { a: 123, b: 456, c: 489, d: 789, e: 458, f: 789 }, { a: 123, b: 456, c: 489, d: 789, e: 458, f: 789 }, { a: 123, b: 456, c: 489, d: 789, e: 458, f: 789 }, { a: 123, b: 456, c: 489, d: 789, e: 458, f: 789 }, { a: 123, b: 456, c: 489, d: 789, e: 458, f: 789 }, { a: 123, b: 456, c: 489, d: 789, e: 458, f: 789 }, { a: 123, b: 456, c: 489, d: 789, e: 458, f: 789 }, { a: 123, b: 456, c: 489, d: 789, e: 458, f: 789 }, { a: 123, b: 456, c: 489, d: 789, e: 458, f: 789 }, { a: 123, b: 456, c: 489, d: 789, e: 458, f: 789 }, { a: 123, b: 456, c: 489, d: 789, e: 458, f: 789 }, ], dataAttribute: [ { title: '第一列', key: 'a' }, { title: '第2列', key: 'b' }, { title: '第3列', key: 'c' }, { title: '第4列', key: 'd' }, { title: '第5列', key: 'e' }, { title: '第6列', key: 'f' } ], tableHeight: (20 + 1) * 96, tableWidth: 200 * 6 + 60 } })
page{ font-size: 26rpx; line-height: 60rpx; color: #222; height: 100%; width: 100%; } .table{ display: block; position: relative; overflow: scroll; width: 100%; height: 100%; } .sticky-box{ } .table__head{ height: 96rpx; white-space: nowrap; position: sticky; top: 0rpx; z-index: 100; height: 88rpx; font-size: 24rpx; line-height: 88rpx; color: #aaabbd; background-color: #f8f8f8; border-bottom: 2rpx solid #ecf1f8; background-color: #fff; white-space: nowrap; display: flex; } .table__head__td{ width: 200rpx; display: flex; justify-content: flex-start; align-items: center; background-color: #fff; box-sizing: border-box; position: relative; overflow: hidden; white-space: nowrap; -o-text-overflow: ellipsis; text-overflow: ellipsis; } .table__head__td:nth-child(1) { padding-left: 24rpx; width: 260rpx; margin-right: 40rpx; position: sticky; z-index: 101; left: 0rpx; } .table__head__td__text{ display: inline; } .table__row{ position: relative; height: 96rpx; white-space: nowrap; display: flex; justify-content: flex-start; align-items: center; border-bottom: 2rpx solid #ecf1f8; } .table__row__td{ overflow: scroll; white-space: nowrap; width: 200rpx; display: inline-block; background-color: #fff; box-sizing: border-box; font-size: 26rpx; line-height: 96rpx; position: relative; overflow: hidden; white-space: nowrap; -o-text-overflow: ellipsis; text-overflow: ellipsis; } .table__row__td:nth-child(1) { margin-right: 40rpx; padding-left: 24rpx; width: 260rpx; position: sticky; z-index: 10; left: 0; }
到此这篇关于微信小程序实现固定表头、列表格组件的文章就介绍到这了,更多相关微信小程序固定表头内容请搜索开心学习网以前的文章或继续浏览下面的相关文章希望大家以后多多支持开心学习网!
您可能感兴趣
- 苹果微信小程序页面空白(iPhoneX安全区域Safe Area底部小黑条在微信小程序和H5的屏幕适配)
- 微信小程序接口返回数据怎么弄(微信小程序页面返回传值的4种解决方案汇总)
- 微信小程序ui聊天窗口(微信小程序实现简单聊天室)
- 微信小程序映射设置(微信小程序虚拟列表的实现示例)
- 微信小程序计数器代码(微信小程序实现计算器案例)
- 微信小程序图片加特效(微信小程序实现可实时改变转速的css3旋转动画实例代码)
- php开发微信小程序后台步骤流程(基于PHP实现微信小程序客服消息功能)
- 微信小程序计时器(微信小程序实现简单的计算器功能)
- 微信小程序静态页面详情(微信小程序基础教程之echart的使用)
- 微信小程序js 抽奖概率(小程序实现筛子抽奖)
- 微信小程序function怎么使用(微信小程序在{{ }}中直接使用函数的方法示例)
- 微信小程序swiper大小调整(微信小程序swiper-dot中的点如何改成滑块详解)
- 微信小程序抽签如何抽中(JavaScript实现班级抽签小程序)
- 微信小程序转盘动画效果(微信小程序实现摇筛子效果)
- 微信小程序日期选择器有星期天(微信小程序 滚动选择器时间日期详解及实例代码)
- 9小时搞定微信小程序开发(关于加快微信小程序开发的一些小建议)
- 蓝天代表什么(蓝天代表什么生肖)
- 今天要吃什么(今天要吃什么菜)
- 营养餐是什么(学校营养餐是什么)
- 谁说女子不如男 范冰冰演的武则天只是其一,另外两位你认识吗(谁说女子不如男)
- 杯酒人生---瓦伦丁酒杯和奥丁格啤酒(杯酒人生---瓦伦丁酒杯和奥丁格啤酒)
- 中秋节买啤酒,预算超过7元试试这8种啤酒,麦香浓郁都是真啤酒(预算超过7元试试这8种啤酒)
热门推荐
- php如何对文本框输入小数的小数点(PHP保留两位小数的几种方法)
- 是选择vps还是云主机(云主机和VPS主机的不同之处)
- IIS8.0安装配置完整图文教程 IIS8.0的Web Server asp设置(IIS8.0安装配置完整图文教程 IIS8.0的Web Server asp设置)
- css时钟(网页中时光轴CSS实现)
- docker容器root密码(docker用root进入容器的操作)
- php建造者模式实例(PHP工厂模式、单例模式与注册树模式实例详解)
- C# Windows服务的创建、安装、调试
- left join on 查询
- angular开发详解(详解Angular动态组件)
- html中的特殊符号编码