- 資訊首頁(yè) > 開(kāi)發(fā)技術(shù) > web開(kāi)發(fā) > JavaScript >
- 微信小程序實(shí)現固定表頭、列表格組件
微信小程序實(shí)現固定表頭固定列表格組件(移動(dòng)端做點(diǎn)小修改通用)
開(kāi)始想用三個(gè)ScrollView去實(shí)現滾動(dòng)聯(lián)動(dòng),固定表頭、列的話(huà),表格內容滾動(dòng)表頭、列也應該對應滾動(dòng),寫(xiě)了demo后發(fā)現監聽(tīng)一個(gè)ScrollView的位置信息去設置另外兩個(gè)ScrollView的位置真機會(huì )很卡,體驗極差
使用position:sticky; 讓表頭相對表格頂部sticky,每行的第一個(gè)元素相對當前行左側sticky。
遇到的問(wèn)題:
index.tsx
/** * 可滑動(dòng)、固定表頭、固定列表格組件 * @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.png'); &--asc-active { background-image: url('https://icon2.png'); } &--desc-active { background-image: url('https://icon3.png'); } } } } &__row{ position: relative; height: 96rpx; white-space: nowrap; display: flex; justify-content: flex-start; align-items: center; border-bottom: 2rpx solid #ecf1f8; &__td{ // .ellipsis(); overflow: scroll; white-space: nowrap; width: 148rpx; // padding-right: 40rpx; display: inline-block; background-color: #fff; position: relative; box-sizing: border-box; font-size: 26rpx; line-height: 96rpx; &:nth-child(1) { margin-right: 40rpx; padding-left: 24rpx; width: 154rpx; position: sticky; z-index: 10; left: 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; }
到此這篇關(guān)于微信小程序實(shí)現固定表頭、列表格組件的文章就介紹到這了,更多相關(guān)微信小程序固定表頭內容請搜索腳本之家以前的文章或繼續瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng )、來(lái)自本網(wǎng)站內容采集于網(wǎng)絡(luò )互聯(lián)網(wǎng)轉載等其它媒體和分享為主,內容觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如侵犯了原作者的版權,請告知一經(jīng)查實(shí),將立刻刪除涉嫌侵權內容,聯(lián)系我們QQ:712375056,同時(shí)歡迎投稿傳遞力量。
Copyright ? 2009-2022 56dr.com. All Rights Reserved. 特網(wǎng)科技 特網(wǎng)云 版權所有 特網(wǎng)科技 粵ICP備16109289號
域名注冊服務(wù)機構:阿里云計算有限公司(萬(wàn)網(wǎng)) 域名服務(wù)機構:煙臺帝思普網(wǎng)絡(luò )科技有限公司(DNSPod) CDN服務(wù):阿里云計算有限公司 百度云 中國互聯(lián)網(wǎng)舉報中心 增值電信業(yè)務(wù)經(jīng)營(yíng)許可證B2
建議您使用Chrome、Firefox、Edge、IE10及以上版本和360等主流瀏覽器瀏覽本網(wǎng)站