mirror of
https://gitee.com/wot-design-uni/wot-design-uni.git
synced 2025-12-06 17:18:40 +08:00
feat: ✨ Table 支持设置不固定表头 (#769)
This commit is contained in:
parent
97c40047e8
commit
b0a2461a1a
@ -2,6 +2,10 @@
|
||||
|
||||
用于展示多条结构类似的数据, 可对数据进行排序等操作。
|
||||
|
||||
::: warning 提示
|
||||
`$LOWEST_VERSION$`后取消了`height`的默认值,需要自行设置,最好设置为`number`类型,方便未来适配虚拟列表。
|
||||
:::
|
||||
|
||||
## 基础用法
|
||||
|
||||
通过`data`设置表格数据。
|
||||
@ -9,7 +13,7 @@
|
||||
::: details 基础用法
|
||||
|
||||
```html
|
||||
<wd-table :data="dataList">
|
||||
<wd-table :data="dataList" :height="400">
|
||||
<wd-table-col prop="name" label="姓名"></wd-table-col>
|
||||
<wd-table-col prop="school" label="求学之所"></wd-table-col>
|
||||
<wd-table-col prop="major" label="专业"></wd-table-col>
|
||||
@ -46,7 +50,7 @@ const dataList = reactive([
|
||||
:::
|
||||
|
||||
```html
|
||||
<wd-table :data="dataList">
|
||||
<wd-table :data="dataList" :height="400">
|
||||
<wd-table-col prop="name" label="姓名" fixed></wd-table-col>
|
||||
<wd-table-col prop="school" label="求学之所"></wd-table-col>
|
||||
<wd-table-col prop="major" label="专业"></wd-table-col>
|
||||
@ -58,7 +62,7 @@ const dataList = reactive([
|
||||
通过`index`设置表格是否显示序号列,默认为`false`。同时也可以传入对象对序号列进行配置,参数同`TableColumnProps`
|
||||
|
||||
```html
|
||||
<wd-table :data="dataList" height="328px" :index="true">
|
||||
<wd-table :data="dataList" height="328px" :index="true" :height="400">
|
||||
<wd-table-col prop="name" label="姓名" sortable></wd-table-col>
|
||||
<wd-table-col prop="grade" label="分数" sortable></wd-table-col>
|
||||
<wd-table-col prop="hobby" label="一言以蔽之" sortable :width="160"></wd-table-col>
|
||||
@ -76,7 +80,7 @@ const dataList = reactive([
|
||||
通过`stripe`设置表格是否展示斑马纹,默认`true`。
|
||||
|
||||
```html
|
||||
<wd-table :data="dataList" :stripe="false">
|
||||
<wd-table :data="dataList" :stripe="false" :height="400">
|
||||
<wd-table-col prop="name" label="姓名"></wd-table-col>
|
||||
<wd-table-col prop="school" label="求学之所"></wd-table-col>
|
||||
<wd-table-col prop="major" label="专业"></wd-table-col>
|
||||
@ -88,7 +92,7 @@ const dataList = reactive([
|
||||
通过`border`设置表格是否展示边框,默认`true`。
|
||||
|
||||
```html
|
||||
<wd-table :data="dataList" :border="false">
|
||||
<wd-table :data="dataList" :border="false" :height="400">
|
||||
<wd-table-col prop="name" label="姓名"></wd-table-col>
|
||||
<wd-table-col prop="school" label="求学之所"></wd-table-col>
|
||||
<wd-table-col prop="major" label="专业"></wd-table-col>
|
||||
@ -97,10 +101,10 @@ const dataList = reactive([
|
||||
|
||||
## 表格高度
|
||||
|
||||
通过`height`设置表格高度,默认为`80vh`。
|
||||
通过`height`设置表格高度,设置高度后会自动固定表头。
|
||||
|
||||
```html
|
||||
<wd-table :data="dataList" height="328px">
|
||||
<wd-table :data="dataList" :height="400">
|
||||
<wd-table-col prop="name" label="姓名"></wd-table-col>
|
||||
<wd-table-col prop="school" label="求学之所"></wd-table-col>
|
||||
<wd-table-col prop="major" label="专业"></wd-table-col>
|
||||
@ -112,7 +116,7 @@ const dataList = reactive([
|
||||
当存在列参与排序时,点击会触发`sort-method`排序事件。
|
||||
|
||||
```html
|
||||
<wd-table :data="dataList" @sort-method="handleSort">
|
||||
<wd-table :data="dataList" @sort-method="handleSort" :height="400">
|
||||
<wd-table-col prop="name" label="姓名"></wd-table-col>
|
||||
<wd-table-col prop="school" label="求学之所" sortable></wd-table-col>
|
||||
<wd-table-col prop="major" label="专业"></wd-table-col>
|
||||
@ -133,7 +137,7 @@ function handleSort(e) {
|
||||
::: details 查看自定义列模版 demo
|
||||
|
||||
```html
|
||||
<wd-table :data="dataList" @sort-method="handleSort">
|
||||
<wd-table :data="dataList" @sort-method="handleSort" :height="400">
|
||||
<wd-table-col prop="name" label="姓名" fixed="true" width="320rpx" sortable></wd-table-col>
|
||||
<wd-table-col prop="grade" label="分数" width="220rpx" sortable>
|
||||
<template #value="{row}">
|
||||
@ -248,13 +252,16 @@ function handleSort(e) {
|
||||
|
||||
:::
|
||||
|
||||
## 结合分页器使用
|
||||
## 不固定表头结合分页器使用
|
||||
|
||||
使用`pagination`组件,通过`v-model`绑定分页器当前页码,通过`total`设置分页器总条数,实现分页加载效果。
|
||||
|
||||
设置`fixed-header`为`false`,取消固定表头。
|
||||
|
||||
::: details 查看结合分页器使用 demo
|
||||
|
||||
```html
|
||||
<wd-table :data="paginationData" height="auto">
|
||||
<wd-table :data="paginationData" :height="400" :fixed-header="false">
|
||||
<wd-table-col prop="name" label="姓名" fixed align="center"></wd-table-col>
|
||||
<wd-table-col prop="grade" label="分数" fixed align="center"></wd-table-col>
|
||||
<wd-table-col prop="hobby" label="一言以蔽之" :width="160"></wd-table-col>
|
||||
@ -439,20 +446,22 @@ const paginationData = computed(() => {
|
||||
return dataList.value.slice((page.value - 1) * pageSize.value, page.value * pageSize.value)
|
||||
})
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
## Attributes
|
||||
|
||||
| 参数 | 说明 | 类型 | 可选值 | 默认值 | 最低版本 |
|
||||
| ---------- | --------------------------------------------------- | ---------------------------- | ------ | ------ | -------- |
|
||||
| --------------- | --------------------------------------------------- | ---------------------------- | ------ | ------ | ---------------- |
|
||||
| data | 显示的数据 | Array | - | - | 0.0.39 |
|
||||
| border | 是否带有边框 | boolean | - | true | 0.0.39 |
|
||||
| stripe | 是否为斑马纹表 | boolean | - | true | 0.0.39 |
|
||||
| height | Table 的高度,默认为`80vh` | string | - | `80vh` | 0.0.39 |
|
||||
| height | Table 的高度,无默认值,设置后自动开启固定表头。 | `number / string` | - | - | 0.0.39 |
|
||||
| rowHeight | 行高 | `number / string` | - | 50 | 0.0.39 |
|
||||
| showHeader | 是否显示表头 | boolean | - | true | 0.0.39 |
|
||||
| ellipsis | 是否超出 2 行隐藏 | boolean | - | true | 0.0.39 |
|
||||
| index | 是否显示索引列,可传入`boolean`也可传入 column 配置 | `boolean / TableColumnProps` | | false | 1.2.19 |
|
||||
| fixed-header | 是否固定表头,需要结合`height`才可以实现固定表头的效果。 | boolean | - | true | $LOWEST_VERSION$ |
|
||||
|
||||
## Events
|
||||
|
||||
|
||||
@ -1,35 +1,35 @@
|
||||
<template>
|
||||
<page-wraper>
|
||||
<demo-block title="基本用法">
|
||||
<wd-table :data="dataList" @sort-method="handleSort" height="328px" @row-click="handleRowClick">
|
||||
<wd-table :data="dataList" @sort-method="handleSort" :height="400" @row-click="handleRowClick">
|
||||
<wd-table-col prop="name" label="姓名" align="center" width="50%"></wd-table-col>
|
||||
<wd-table-col prop="grade" label="分数" align="center" width="50%"></wd-table-col>
|
||||
</wd-table>
|
||||
</demo-block>
|
||||
|
||||
<demo-block title="无边框">
|
||||
<wd-table :data="dataList" @sort-method="handleSort" height="328px" :border="false" @row-click="handleRowClick">
|
||||
<wd-table :data="dataList" @sort-method="handleSort" :height="400" :border="false" @row-click="handleRowClick">
|
||||
<wd-table-col prop="name" label="姓名" align="center" width="50%"></wd-table-col>
|
||||
<wd-table-col prop="grade" label="分数" align="center" width="50%"></wd-table-col>
|
||||
</wd-table>
|
||||
</demo-block>
|
||||
|
||||
<demo-block title="无斑马纹">
|
||||
<wd-table :data="dataList" @sort-method="handleSort" height="328px" :stripe="false" @row-click="handleRowClick">
|
||||
<wd-table :data="dataList" @sort-method="handleSort" :height="400" :stripe="false" @row-click="handleRowClick">
|
||||
<wd-table-col prop="name" label="姓名" align="center" width="50%"></wd-table-col>
|
||||
<wd-table-col prop="grade" label="分数" align="center" width="50%"></wd-table-col>
|
||||
</wd-table>
|
||||
</demo-block>
|
||||
|
||||
<demo-block title="不展示表头">
|
||||
<wd-table :data="dataList" @sort-method="handleSort" height="328px" :show-header="false" @row-click="handleRowClick">
|
||||
<wd-table :data="dataList" @sort-method="handleSort" :height="400" :show-header="false" @row-click="handleRowClick">
|
||||
<wd-table-col prop="name" label="姓名" align="center" width="50%"></wd-table-col>
|
||||
<wd-table-col prop="grade" label="分数" align="center" width="50%"></wd-table-col>
|
||||
</wd-table>
|
||||
</demo-block>
|
||||
|
||||
<demo-block title="固定列">
|
||||
<wd-table :data="dataList" @sort-method="handleSort" @row-click="handleRowClick" height="328px">
|
||||
<wd-table :data="dataList" @sort-method="handleSort" @row-click="handleRowClick" :height="400">
|
||||
<wd-table-col prop="name" label="姓名" fixed sortable align="center"></wd-table-col>
|
||||
<wd-table-col prop="grade" label="分数" fixed sortable align="center"></wd-table-col>
|
||||
<wd-table-col prop="hobby" label="一言以蔽之" sortable :width="160"></wd-table-col>
|
||||
@ -40,7 +40,7 @@
|
||||
</demo-block>
|
||||
|
||||
<demo-block title="显示索引">
|
||||
<wd-table :data="dataList" height="328px" @sort-method="handleSort" :index="{ align: 'center' }">
|
||||
<wd-table :data="dataList" :height="400" @sort-method="handleSort" :index="{ align: 'center' }">
|
||||
<wd-table-col prop="name" label="姓名" sortable align="center"></wd-table-col>
|
||||
<wd-table-col prop="grade" label="分数" sortable align="center"></wd-table-col>
|
||||
<wd-table-col prop="hobby" label="一言以蔽之" sortable :width="160"></wd-table-col>
|
||||
@ -51,7 +51,7 @@
|
||||
</demo-block>
|
||||
|
||||
<demo-block title="自定义列模板">
|
||||
<wd-table :data="dataList" @sort-method="handleSort" @row-click="handleRowClick" height="328px">
|
||||
<wd-table :data="dataList" @sort-method="handleSort" @row-click="handleRowClick" :height="400">
|
||||
<wd-table-col prop="name" label="姓名" fixed sortable align="center"></wd-table-col>
|
||||
<wd-table-col prop="grade" label="分数" fixed sortable align="center">
|
||||
<template #value="{ row }">
|
||||
@ -69,8 +69,8 @@
|
||||
</wd-table>
|
||||
</demo-block>
|
||||
|
||||
<demo-block title="结合分页器">
|
||||
<wd-table :data="paginationData" height="auto">
|
||||
<demo-block title="不固定表头结合分页器">
|
||||
<wd-table :data="paginationData" :fixed-header="false">
|
||||
<wd-table-col prop="name" label="姓名" fixed align="center"></wd-table-col>
|
||||
<wd-table-col prop="grade" label="分数" fixed align="center"></wd-table-col>
|
||||
<wd-table-col prop="hobby" label="一言以蔽之" :width="160"></wd-table-col>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<view
|
||||
:class="`wd-table-col ${fixed ? 'wd-table-col--fixed' : ''} ${isLastFixed && isDef(table) && table.scrollLeft ? 'is-shadow' : ''}`"
|
||||
:class="`wd-table-col ${fixed ? 'wd-table-col--fixed' : ''} ${isLastFixed && isDef(table) && table.state.scrollLeft ? 'is-shadow' : ''}`"
|
||||
:style="columnStyle"
|
||||
>
|
||||
<view
|
||||
@ -27,7 +27,7 @@ export default {
|
||||
}
|
||||
</script>
|
||||
<script lang="ts" setup>
|
||||
import { type CSSProperties, computed, ref, watch } from 'vue'
|
||||
import { type CSSProperties, computed, ref } from 'vue'
|
||||
import { addUnit, isDef, objToStyle, isOdd, isFunction } from '../common/util'
|
||||
import { tableColumnProps, type SortDirection } from './types'
|
||||
import { useParent } from '../composables/useParent'
|
||||
@ -100,7 +100,7 @@ const columnStyle = computed(() => {
|
||||
*/
|
||||
const cellStyle = computed(() => {
|
||||
let style: CSSProperties = {}
|
||||
const rowHeight: string | number = isDef(table) ? table.props.rowHeight : '80rpx' // 自定义行高
|
||||
const rowHeight: string | number = isDef(table) ? table.props.rowHeight : 50 // 自定义行高
|
||||
if (isDef(rowHeight)) {
|
||||
style['height'] = addUnit(rowHeight)
|
||||
}
|
||||
|
||||
@ -43,7 +43,6 @@
|
||||
border: 1px solid $-table-border-color;
|
||||
}
|
||||
|
||||
|
||||
:deep() {
|
||||
.wd-table-col:last-child {
|
||||
.wd-table__cell {
|
||||
@ -72,6 +71,12 @@
|
||||
|
||||
@include e(content) {
|
||||
display: flex;
|
||||
|
||||
@include m(header) {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 2
|
||||
}
|
||||
}
|
||||
|
||||
@include e(cell) {
|
||||
@ -127,6 +132,26 @@
|
||||
}
|
||||
}
|
||||
|
||||
@include e(wrapper) {
|
||||
width: 100%;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
@include e(inner) {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
@include e(header-row) {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@include e(body) {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@include e(value) {
|
||||
@include when(ellipsis) {
|
||||
|
||||
@ -1,14 +1,14 @@
|
||||
/*
|
||||
* @Author: weisheng
|
||||
* @Date: 2024-03-15 11:36:12
|
||||
* @LastEditTime: 2024-07-18 19:02:32
|
||||
* @LastEditTime: 2024-12-08 23:22:26
|
||||
* @LastEditors: weisheng
|
||||
* @Description:
|
||||
* @FilePath: \wot-design-uni\src\uni_modules\wot-design-uni\components\wd-table\types.ts
|
||||
* @FilePath: /wot-design-uni/src/uni_modules/wot-design-uni/components/wd-table/types.ts
|
||||
* 记得注释
|
||||
*/
|
||||
import type { CSSProperties, ExtractPropTypes, InjectionKey } from 'vue'
|
||||
import { baseProps, makeBooleanProp, makeNumericProp, makeRequiredProp, makeStringProp } from '../common/props'
|
||||
import { baseProps, makeBooleanProp, makeNumericProp, makeRequiredProp, numericProp } from '../common/props'
|
||||
import type { TableColumnProps } from '../wd-table-col/types'
|
||||
import type { PropType } from 'vue'
|
||||
|
||||
@ -29,7 +29,7 @@ export const tableProps = {
|
||||
/**
|
||||
* Table 的高度
|
||||
*/
|
||||
height: makeStringProp('80vh'),
|
||||
height: numericProp,
|
||||
/**
|
||||
* 行高
|
||||
*/
|
||||
@ -48,14 +48,17 @@ export const tableProps = {
|
||||
index: {
|
||||
type: [Object, Boolean] as PropType<boolean | Omit<Partial<TableColumnProps>, 'prop'>>,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
fixedHeader: makeBooleanProp(true)
|
||||
}
|
||||
|
||||
export type TableProps = ExtractPropTypes<typeof tableProps>
|
||||
|
||||
export type TableProvide = {
|
||||
props: Omit<TableProps, 'index' | 'customStyle' | 'customClass'>
|
||||
state: {
|
||||
scrollLeft: number
|
||||
}
|
||||
rowClick: (index: number) => void
|
||||
getIsLastFixed: (column: { fixed: boolean; prop: string }) => boolean
|
||||
getFixedStyle: (index: number, style: CSSProperties) => CSSProperties
|
||||
|
||||
@ -1,18 +1,19 @@
|
||||
<template>
|
||||
<view :class="`wd-table ${border ? 'is-border' : ''} ${customClass}`" :style="tableStyle">
|
||||
<template v-if="fixedHeader">
|
||||
<scroll-view
|
||||
:enable-flex="true"
|
||||
:throttle="false"
|
||||
:scrollLeft="reactiveState.scrollLeft"
|
||||
:scrollLeft="state.scrollLeft"
|
||||
:scroll-x="true"
|
||||
class="wd-table__header"
|
||||
@scroll="scroll"
|
||||
v-if="showHeader"
|
||||
>
|
||||
<view id="table-header" class="wd-table__content" :style="realWidthStyle" style="position: sticky; top: 0; z-index: 2">
|
||||
<view id="table-header" class="wd-table__content wd-table__content--header" :style="realWidthStyle">
|
||||
<view
|
||||
:class="`wd-table__cell ${border ? 'is-border' : ''} ${column.fixed ? 'is-fixed' : ''} ${stripe ? 'is-stripe' : ''} is-${column.align} ${
|
||||
getIsLastFixed(column) && reactiveState.scrollLeft ? 'is-shadow' : ''
|
||||
getIsLastFixed(column) && state.scrollLeft ? 'is-shadow' : ''
|
||||
}`"
|
||||
:style="getCellStyle(index)"
|
||||
v-for="(column, index) in children"
|
||||
@ -37,7 +38,7 @@
|
||||
:throttle="false"
|
||||
:scroll-x="true"
|
||||
@scroll="scroll"
|
||||
:scrollLeft="reactiveState.scrollLeft"
|
||||
:scrollLeft="state.scrollLeft"
|
||||
>
|
||||
<view id="table-body" class="wd-table__content" :style="realWidthStyle">
|
||||
<wd-table-col
|
||||
@ -56,6 +57,53 @@
|
||||
<slot></slot>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</template>
|
||||
<!-- 非固定表头时使用单个scroll-view -->
|
||||
<template v-else>
|
||||
<scroll-view class="wd-table__wrapper" :enable-flex="true" :throttle="false" :scroll-x="true" @scroll="scroll" :scrollLeft="state.scrollLeft">
|
||||
<view class="wd-table__inner" :style="realWidthStyle">
|
||||
<!-- 表头部分 -->
|
||||
<view v-if="showHeader" class="wd-table__header-row">
|
||||
<view
|
||||
v-for="(column, index) in children"
|
||||
:key="index"
|
||||
:class="`wd-table__cell ${border ? 'is-border' : ''} ${column.fixed ? 'is-fixed' : ''} ${stripe ? 'is-stripe' : ''} is-${
|
||||
column.align
|
||||
} ${getIsLastFixed(column) && state.scrollLeft ? 'is-shadow' : ''}`"
|
||||
:style="getCellStyle(index)"
|
||||
>
|
||||
<wd-sort-button
|
||||
v-if="column.sortable"
|
||||
v-model="column.$.exposed!.sortDirection.value"
|
||||
allow-reset
|
||||
:line="false"
|
||||
:title="column.label"
|
||||
@change="({ value }) => handleSortChange(value, index)"
|
||||
/>
|
||||
<text v-else :class="`wd-table__value ${ellipsis ? 'is-ellipsis' : ''}`">{{ column.label }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 表格内容部分 -->
|
||||
<view class="wd-table__content" :style="bodyStyle">
|
||||
<wd-table-col
|
||||
v-if="index !== false"
|
||||
:prop="indexColumn.prop"
|
||||
:label="indexColumn.label"
|
||||
:width="indexColumn.width"
|
||||
:sortable="indexColumn.sortable"
|
||||
:fixed="indexColumn.fixed"
|
||||
:align="indexColumn.align"
|
||||
>
|
||||
<template #value="{ index }">
|
||||
<text>{{ index + 1 }}</text>
|
||||
</template>
|
||||
</wd-table-col>
|
||||
<slot></slot>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</template>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
@ -86,17 +134,13 @@ const { translate } = useTranslate('tableCol')
|
||||
const props = defineProps(tableProps)
|
||||
const emit = defineEmits(['sort-method', 'row-click'])
|
||||
|
||||
const reactiveState = reactive<TableProvide>({
|
||||
props,
|
||||
scrollLeft: 0,
|
||||
rowClick,
|
||||
getIsLastFixed,
|
||||
getFixedStyle
|
||||
const state = reactive({
|
||||
scrollLeft: 0
|
||||
})
|
||||
|
||||
const { linkChildren, children } = useChildren<TableColumnInstance, TableProvide>(TABLE_KEY)
|
||||
|
||||
linkChildren(reactiveState)
|
||||
linkChildren({ props, state, rowClick, getIsLastFixed, getFixedStyle })
|
||||
|
||||
const indexUUID = uuid()
|
||||
const indexColumn = ref<TableColumnProps>({
|
||||
@ -227,10 +271,7 @@ function handleSortChange(value: SortDirection, index: number) {
|
||||
* 滚动事件
|
||||
*/
|
||||
function handleScroll(event: any) {
|
||||
if (!props.showHeader) {
|
||||
return
|
||||
}
|
||||
reactiveState.scrollLeft = event.detail.scrollLeft
|
||||
state.scrollLeft = event.detail.scrollLeft
|
||||
}
|
||||
|
||||
function rowClick(index: number) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user