需求背景
公司面向B端的用户需要看大量报表,但是在滚动的时候经常看不到数据对比,看着看着就不知道对应的数据是啥含义了,如是领导让我弄一个固定表头和前面两行的效果。想到小程序没有table组件就只能自己手撸一个组件咯,本篇文章就基于这样的场景诞生了!
需求设计
原有功能点
1.固定顶部标题栏
2.固定左侧某几列
复制代码
延伸功能点
1.标题栏配置
2.固定栏的数量配置
3.格子高度
4.格子宽度
5.组件高度
复制代码
功能实现
功能的核心点是:利用position:sticky这个粘性属性来实现,避免获取dom用js来算位置进行定位。
复制代码
dom结构
<!-- max-height:最大高度;--hegiht: 格子高度-->
<view class="table" style="max-height:{{height}}px;--height:{{cellHeight+'rpx'}}">
<view class="content-list" style="width:{{normalWidth+fixedWidth}}rpx">
<view class="left-box">
<!-- 左侧固定部分 -->
<!-- 左侧固定区域标题栏 -->
<view style="width:{{fixedWidth}}rpx;display:flex;position:sticky;top:0; ">
<view class="header-title" wx:for="{{fixedKey}}" wx:key="index" style="flex-basis:{{item.width}}rpx;">
{{columns[item.index].name}}
</view>
</view>
<!-- 固定区域的数据 -->
<view wx:for="{{fixedData}}" wx:key="index" style="width:{{fixedWidth}}rpx;display:flex;">
<view class="header-title" wx:for="{{fixedKey}}" wx:key="keyIndex" wx:for-index="keyIndex" wx:for-item="keyItem" style="flex-basis:{{keyItem.width}}rpx">
{{item[keyItem['key']]}}
</view>
</view>
</view>
<view class="right-box">
<!-- 右侧非固定部分 -->
<view style="display:flex;position:sticky;top:0;">
<!-- 顶部标题栏固定 -->
<view class="header-title" wx:for="{{normalKey}}" wx:key="index" style="flex-basis:{{item.width}}rpx">
{{columns[item.index].name}}
</view>
</view>
<view class="" style="display:flex;width:{{normalWidth}}rpx;">
<!-- 非固定区域的数据 -->
<view wx:for="{{normalKey}}" wx:key="keyIndex" wx:for-index="keyIndex" wx:for-item="keyItem" style="display:flex;flex-wrap:wrap;flex-basis:{{keyItem.width}}rpx">
<view class="header-title" wx:for="{{normalData}}" wx:key="index" style="flex-basis:{{keyItem.width}}rpx">
{{item[keyItem['key']]}}
</view>
</view>
</view>
</view>
</view>
</view>
复制代码
样式
/* compoent/table/index.wxss */
.table {
/* width: 100%; */
overflow-x:auto;
}
.header{
overflow-x: auto;
position: sticky;
display: flex;
}
.header-title {
height: var(--height);
box-sizing: border-box;
font-size: 12px;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
white-space: nowrap;
background-color: #2E324A;
color: #fff;
}
.content-list {
display: flex;
}
.left-box {
z-index: 9;
left: 0;
position: sticky;
}
复制代码
js
// compoent/table/index.js
/**
*
*/
Component({
/**
* 组件的属性列表
*/
properties: {
/**
* 组件高度 默认500 单位px
*/
height:{
type:Number,
value:500
},
/**
* 表头配置
*/
columns:{
type:Array,
value:[]
},
source:{ // 源数据
type:Array,
value:[]
},
fixedCount:{ // 定在左侧默认的数量
type:Number,
value:1
},
cellHeight:{ // 格子高度 默认80 单位rpx
type:Number,
value:80
},
cellWidth:{ // 格子宽度 默认150 单位 rpx
type:Number,
value:150
}
},
/**
* 组件的初始数据
*/
data: {
columns:[
{
name:'口碑', //标题名称
key:'shopName' //对应的数据‘key’
},
], // 标题栏配置
normalKey:[], // 非固定标题的key
normalData:[], // 非固定标题的数据
fixedData:[], //固定标题的数据
fixedKey:[],//需要固定在左侧的参数key
fixedWidth:0, //固定标题区域的宽度
normalWidth:0,//非固定区域的宽度
},
lifetimes:{
attached:function(){
let {source} = this.data
this._updateData(source)
}
},
observers:{
// 监听 源数据的变
'source':function(source){
// 更新table数据
this._updateData(source)
console.log(this.data);
}
},
/**
* 组件的方法列表
*/
methods: {
_updateData(source){
let {columns,fixedCount,fixedWidth,normalWidth,cellWidth}=this.data
let [fixedKey,fixedData,normalKey,normalData]=[[],[],[],[]]
if(columns&& columns.length>0){
columns.forEach((item,index) => {
if(item.fixed && fixedCount>0 && fixedKey.length <= fixedCount){
fixedKey.push({
key:item.key,
index:index,
width:item.width?item.width:cellWidth
})
}else {
normalKey.push({
key:item.key,
index:index,
width:item.width?item.width:cellWidth
})
}
});
}
if(fixedKey.length>0){
fixedWidth=0
source.forEach((item,index)=>{
let temp={}
fixedKey.forEach(sonItem=>{
let tempKey=sonItem.key
if(sonItem.key=='rank'){
temp[tempKey]= index+1
}else{
temp[tempKey]=item[tempKey]
}
})
fixedData.push(temp)
})
fixedKey.forEach(item=>{
fixedWidth += item.width
})
}
if(normalKey.length>0){
normalWidth=0
source.forEach((item,index)=>{
let temp={}
normalKey.forEach(sonItem=>{
let tempKey=sonItem.key
if(sonItem=='rank'){
temp[tempKey]= index+1
}else{
temp[tempKey]=item[tempKey]
}
})
normalData.push(temp)
})
normalKey.forEach(item=>{
normalWidth += item.width
})
}
this.setData({
columns,
fixedKey,
normalKey,
fixedData,
normalData,
fixedWidth,
normalWidth
})
}
}
})
复制代码
效果图
无图无真相,实际效果如下图:
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END