mirror of
https://github.com/tusen-ai/naive-ui.git
synced 2024-12-27 05:00:48 +08:00
fix(data-table): not showing scrollbar when table-layout is auto, closes #518
This commit is contained in:
parent
8314e674e7
commit
78c3845f5e
@ -20,6 +20,7 @@
|
||||
- Fix `n-layout-sider`'s `width` prop can't be string, closes [#607](https://github.com/TuSimple/naive-ui/issues/607).
|
||||
- Fix `n-slider` prop `disabled` doesn't work, closes [#641](https://github.com/TuSimple/naive-ui/issues/641).
|
||||
- Fix `n-input` show clear button when readonly.
|
||||
- Fix `n-data-table` doesn't show scrollbar when table-layout is auto, closes [#518](https://github.com/TuSimple/naive-ui/issues/518).
|
||||
|
||||
## 2.15.6 (2021-07-23)
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
- 修复 `n-layout-sider` `width` 不能为字符串,关闭 [#607](https://github.com/TuSimple/naive-ui/issues/607)
|
||||
- 修复 `n-slider` `disabled` 属性不生效,关闭 [#641](https://github.com/TuSimple/naive-ui/issues/641)
|
||||
- 修复 `n-input` 在只读时仍展示清除按钮
|
||||
- 修复 `n-data-table` 在 table-layout 为 auto 时不展示滚动条,关闭 [#518](https://github.com/TuSimple/naive-ui/issues/518)
|
||||
|
||||
## 2.15.6 (2021-07-23)
|
||||
|
||||
|
@ -36,6 +36,7 @@ ajax-usage
|
||||
virtual
|
||||
custom-filter-menu
|
||||
tree
|
||||
scroll-debug
|
||||
```
|
||||
|
||||
## Props
|
||||
|
134
src/data-table/demos/zhCN/scroll-debug.demo.md
Normal file
134
src/data-table/demos/zhCN/scroll-debug.demo.md
Normal file
@ -0,0 +1,134 @@
|
||||
# Scroll Debug
|
||||
|
||||
```html
|
||||
Auto Layout Overflow, No Max Height
|
||||
<n-data-table :columns="columns" :data="data" />
|
||||
|
||||
Auto Layout Overflow, Max Height
|
||||
<n-data-table :columns="columns" :data="data" :max-height="60" />
|
||||
|
||||
Fixed Layout Overflow, No Max Height
|
||||
<n-data-table :columns="columns" :data="data" table-layout="fixed" />
|
||||
|
||||
Fixed Layout Overflow, Max Height
|
||||
<n-data-table
|
||||
:columns="columns"
|
||||
:data="data"
|
||||
table-layout="fixed"
|
||||
:max-height="60"
|
||||
/>
|
||||
|
||||
Auto Layout No Overflow, No Max Height
|
||||
<n-data-table :columns="columns" :data="data1" />
|
||||
|
||||
Auto Layout No Overflow, Max Height
|
||||
<n-data-table :columns="columns" :data="data1" :max-height="60" />
|
||||
|
||||
Fixed Layout No Overflow, No Max Height
|
||||
<n-data-table :columns="columns" :data="data1" table-layout="fixed" />
|
||||
|
||||
Fixed Layout No Overflow, Max Height
|
||||
<n-data-table
|
||||
:columns="columns"
|
||||
:data="data1"
|
||||
table-layout="fixed"
|
||||
:max-height="60"
|
||||
/>
|
||||
|
||||
Auto Layout No Overflow, No Max Height, Small Scroll X
|
||||
<n-data-table :columns="columns" :data="data1" :scroll-x="300" />
|
||||
|
||||
Auto Layout No Overflow, Max Height
|
||||
<n-data-table
|
||||
:columns="columns"
|
||||
:data="data1"
|
||||
:max-height="60"
|
||||
:scroll-x="300"
|
||||
/>
|
||||
|
||||
Fixed Layout No Overflow, No Max Height
|
||||
<n-data-table
|
||||
:columns="columns"
|
||||
:data="data1"
|
||||
table-layout="fixed"
|
||||
:scroll-x="300"
|
||||
/>
|
||||
|
||||
Fixed Layout No Overflow, Max Height
|
||||
<n-data-table
|
||||
:columns="columns"
|
||||
:data="data1"
|
||||
table-layout="fixed"
|
||||
:max-height="60"
|
||||
:scroll-x="300"
|
||||
/>
|
||||
```
|
||||
|
||||
```js
|
||||
import { defineComponent, h } from 'vue'
|
||||
|
||||
const label0 =
|
||||
'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy'
|
||||
|
||||
const label =
|
||||
'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
|
||||
|
||||
export default defineComponent({
|
||||
setup () {
|
||||
return {
|
||||
columns: [
|
||||
{
|
||||
key: '1',
|
||||
title: '1',
|
||||
render (rowData) {
|
||||
return h('div', { style: 'white-space: nowrap;' }, rowData['1'])
|
||||
}
|
||||
},
|
||||
{
|
||||
key: '2',
|
||||
title: '2',
|
||||
render (rowData) {
|
||||
return h('div', { style: 'white-space: nowrap;' }, rowData['2'])
|
||||
}
|
||||
}
|
||||
],
|
||||
data: [
|
||||
{
|
||||
1: label0,
|
||||
2: label
|
||||
},
|
||||
{
|
||||
1: label0,
|
||||
2: label
|
||||
},
|
||||
{
|
||||
1: label0,
|
||||
2: label
|
||||
},
|
||||
{
|
||||
1: label0,
|
||||
2: label
|
||||
}
|
||||
],
|
||||
data1: [
|
||||
{
|
||||
1: 'x',
|
||||
2: 'x'
|
||||
},
|
||||
{
|
||||
1: 'x',
|
||||
2: 'x'
|
||||
},
|
||||
{
|
||||
1: 'x',
|
||||
2: 'x'
|
||||
},
|
||||
{
|
||||
1: 'x',
|
||||
2: 'x'
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
@ -10,6 +10,7 @@ import {
|
||||
renderSlot,
|
||||
CSSProperties
|
||||
} from 'vue'
|
||||
import { createId } from 'seemly'
|
||||
import { useConfig, useLocale, useTheme } from '../../_mixins'
|
||||
import type { ThemeProps } from '../../_mixins'
|
||||
import { NEmpty } from '../../empty'
|
||||
@ -42,7 +43,6 @@ import { dataTableInjectionKey } from './interface'
|
||||
import style from './styles/index.cssr'
|
||||
import { useGroupHeader } from './use-group-header'
|
||||
import { useExpand } from './use-expand'
|
||||
import { createId } from 'seemly'
|
||||
|
||||
export const dataTableProps = {
|
||||
...(useTheme.props as ThemeProps<DataTableTheme>),
|
||||
@ -242,7 +242,8 @@ export default defineComponent({
|
||||
const bodyWidthRef = ref<number | null>(null)
|
||||
const scrollPartRef = ref<'head' | 'body'>('body')
|
||||
const mainTableInstRef = ref<MainTableRef | null>(null)
|
||||
const { rowsRef, colsRef, dataRelatedColsRef } = useGroupHeader(props)
|
||||
const { rowsRef, colsRef, dataRelatedColsRef, hasEllpisisRef } =
|
||||
useGroupHeader(props)
|
||||
const {
|
||||
treeMateRef,
|
||||
mergedCurrentPageRef,
|
||||
@ -300,6 +301,17 @@ export default defineComponent({
|
||||
mergedCurrentPageRef
|
||||
})
|
||||
const { localeRef } = useLocale('DataTable')
|
||||
const mergedTableLayoutRef = computed(() => {
|
||||
// Layout
|
||||
// virtual |descrete header | ellpisis => fixed
|
||||
// = virtual | maxHeight | ellpisis => fixed
|
||||
if (
|
||||
props.virtualScroll ||
|
||||
props.maxHeight !== undefined ||
|
||||
hasEllpisisRef.value
|
||||
) { return 'fixed' }
|
||||
return props.tableLayout
|
||||
})
|
||||
provide(dataTableInjectionKey, {
|
||||
indentRef: toRef(props, 'indent'),
|
||||
firstContentfulColIndexRef,
|
||||
@ -354,7 +366,7 @@ export default defineComponent({
|
||||
'--action-divider-color': actionDividerColor
|
||||
} as CSSProperties
|
||||
}),
|
||||
tableLayoutRef: toRef(props, 'tableLayout'),
|
||||
mergedTableLayoutRef,
|
||||
maxHeightRef: toRef(props, 'maxHeight'),
|
||||
minHeightRef: toRef(props, 'minHeight'),
|
||||
syncScrollState,
|
||||
|
@ -7,7 +7,8 @@ import {
|
||||
VNode,
|
||||
watchEffect,
|
||||
onUnmounted,
|
||||
PropType
|
||||
PropType,
|
||||
CSSProperties
|
||||
} from 'vue'
|
||||
import { pxfy, repeat } from 'seemly'
|
||||
import { VirtualList, VirtualListInst } from 'vueuc'
|
||||
@ -120,11 +121,12 @@ export default defineComponent({
|
||||
virtualScrollRef,
|
||||
componentId,
|
||||
scrollPartRef,
|
||||
tableLayoutRef,
|
||||
mergedTableLayoutRef,
|
||||
hasChildrenRef,
|
||||
firstContentfulColIndexRef,
|
||||
indentRef,
|
||||
rowPropsRef,
|
||||
maxHeightRef,
|
||||
setHeaderScrollLeft,
|
||||
doUpdateExpandedRowKeys,
|
||||
handleTableBodyScroll,
|
||||
@ -258,11 +260,12 @@ export default defineComponent({
|
||||
hoverKey: hoverKeyRef,
|
||||
mergedSortState: mergedSortStateRef,
|
||||
virtualScroll: virtualScrollRef,
|
||||
tableLayout: tableLayoutRef,
|
||||
mergedTableLayout: mergedTableLayoutRef,
|
||||
hasChildren: hasChildrenRef,
|
||||
firstContentfulColIndex: firstContentfulColIndexRef,
|
||||
indent: indentRef,
|
||||
rowProps: rowPropsRef,
|
||||
maxHeight: maxHeightRef,
|
||||
setHeaderScrollLeft,
|
||||
handleMouseenterTable,
|
||||
handleVirtualListScroll,
|
||||
@ -282,16 +285,28 @@ export default defineComponent({
|
||||
scrollX,
|
||||
mergedClsPrefix,
|
||||
virtualScroll,
|
||||
maxHeight,
|
||||
mergedTableLayout,
|
||||
onResize,
|
||||
setHeaderScrollLeft
|
||||
} = this
|
||||
const contentStyle = {
|
||||
width: '100%',
|
||||
minWidth: formatLength(scrollX)
|
||||
const scrollable = scrollX !== undefined || maxHeight !== undefined
|
||||
|
||||
// For a basic table with auto layout whose content may overflow we will
|
||||
// make it scrollable, which differs from browser's native behavior.
|
||||
// For native behavior, see
|
||||
// https://developer.mozilla.org/en-US/docs/Web/CSS/table-layout
|
||||
const isBasicAutoLayout = !scrollable && mergedTableLayout === 'auto'
|
||||
const xScrollable = scrollX !== undefined || isBasicAutoLayout
|
||||
|
||||
const contentStyle: CSSProperties = {
|
||||
minWidth: formatLength(scrollX) || '100%'
|
||||
}
|
||||
if (scrollX) contentStyle.width = '100%'
|
||||
return (
|
||||
<NScrollbar
|
||||
ref="scrollbarInstRef"
|
||||
scrollable={scrollable || isBasicAutoLayout}
|
||||
class={`${mergedClsPrefix}-data-table-base-table-body`}
|
||||
theme={mergedTheme.peers.Scrollbar}
|
||||
themeOverrides={mergedTheme.peerOverrides.Scrollbar}
|
||||
@ -300,7 +315,7 @@ export default defineComponent({
|
||||
content={virtualScroll ? this.virtualListContent : undefined}
|
||||
horizontalRailStyle={{ zIndex: 3 }}
|
||||
verticalRailStyle={{ zIndex: 3 }}
|
||||
xScrollable
|
||||
xScrollable={xScrollable}
|
||||
onScroll={virtualScroll ? undefined : this.handleTableBodyScroll}
|
||||
internalOnUpdateScrollLeft={setHeaderScrollLeft}
|
||||
onResize={onResize}
|
||||
@ -379,8 +394,6 @@ export default defineComponent({
|
||||
|
||||
const { length: rowCount } = mergedData
|
||||
|
||||
let hasEllipsis = false
|
||||
|
||||
const indentStyle = hasChildren
|
||||
? { width: pxfy(this.indent) }
|
||||
: undefined
|
||||
@ -441,7 +454,6 @@ export default defineComponent({
|
||||
}
|
||||
const hoverKey = isCrossRowTd ? this.hoverKey : null
|
||||
const { ellipsis } = column
|
||||
if (!hasEllipsis && ellipsis) hasEllipsis = true
|
||||
return (
|
||||
<td
|
||||
key={colKey}
|
||||
@ -624,8 +636,7 @@ export default defineComponent({
|
||||
onMouseleave={handleMouseleaveTable}
|
||||
onMouseenter={handleMouseenterTable}
|
||||
style={{
|
||||
tableLayout:
|
||||
this.showHeader && !hasEllipsis ? this.tableLayout : 'fixed'
|
||||
tableLayout: this.mergedTableLayout
|
||||
}}
|
||||
>
|
||||
<colgroup>
|
||||
|
@ -190,7 +190,7 @@ export interface DataTableInjection {
|
||||
virtualScrollRef: Ref<boolean>
|
||||
bodyWidthRef: Ref<number | null>
|
||||
scrollPartRef: Ref<'head' | 'body'>
|
||||
tableLayoutRef: Ref<'auto' | 'fixed'>
|
||||
mergedTableLayoutRef: Ref<'auto' | 'fixed'>
|
||||
maxHeightRef: Ref<string | number | undefined>
|
||||
minHeightRef: Ref<string | number | undefined>
|
||||
rowPropsRef: Ref<CreateRowProps | undefined>
|
||||
|
@ -22,15 +22,14 @@ export interface ColItem {
|
||||
}
|
||||
|
||||
type RowItemMap = WeakMap<TableColumn, RowItem>
|
||||
function getRowsAndCols (
|
||||
columns: TableColumns
|
||||
): {
|
||||
rows: RowItem[][]
|
||||
cols: ColItem[]
|
||||
dataRelatedCols: Array<
|
||||
TableSelectionColumn | TableBaseColumn | TableExpandColumn
|
||||
>
|
||||
} {
|
||||
function getRowsAndCols (columns: TableColumns): {
|
||||
hasEllpisis: boolean
|
||||
rows: RowItem[][]
|
||||
cols: ColItem[]
|
||||
dataRelatedCols: Array<
|
||||
TableSelectionColumn | TableBaseColumn | TableExpandColumn
|
||||
>
|
||||
} {
|
||||
const rows: RowItem[][] = []
|
||||
const cols: ColItem[] = []
|
||||
const dataRelatedCols: Array<
|
||||
@ -39,6 +38,7 @@ function getRowsAndCols (
|
||||
const rowItemMap: RowItemMap = new WeakMap()
|
||||
let maxDepth = -1
|
||||
let totalRowSpan = 0
|
||||
let hasEllpisis = false
|
||||
function ensureMaxDepth (columns: TableColumns, currentDepth: number): void {
|
||||
if (currentDepth > maxDepth) {
|
||||
rows[currentDepth] = []
|
||||
@ -54,6 +54,7 @@ function getRowsAndCols (
|
||||
column
|
||||
})
|
||||
totalRowSpan += 1
|
||||
hasEllpisis = !!column.ellipsis
|
||||
dataRelatedCols.push(column)
|
||||
}
|
||||
}
|
||||
@ -110,25 +111,26 @@ function getRowsAndCols (
|
||||
ensureColLayout(columns, 0, true)
|
||||
|
||||
return {
|
||||
hasEllpisis,
|
||||
rows,
|
||||
cols,
|
||||
dataRelatedCols
|
||||
}
|
||||
}
|
||||
|
||||
export function useGroupHeader (
|
||||
props: DataTableSetupProps
|
||||
): {
|
||||
rowsRef: ComputedRef<RowItem[][]>
|
||||
colsRef: ComputedRef<ColItem[]>
|
||||
dataRelatedColsRef: ComputedRef<
|
||||
Array<TableSelectionColumn | TableBaseColumn | TableExpandColumn>
|
||||
>
|
||||
} {
|
||||
export function useGroupHeader (props: DataTableSetupProps): {
|
||||
rowsRef: ComputedRef<RowItem[][]>
|
||||
colsRef: ComputedRef<ColItem[]>
|
||||
hasEllpisisRef: ComputedRef<boolean>
|
||||
dataRelatedColsRef: ComputedRef<
|
||||
Array<TableSelectionColumn | TableBaseColumn | TableExpandColumn>
|
||||
>
|
||||
} {
|
||||
const rowsAndCols = computed(() => getRowsAndCols(props.columns))
|
||||
return {
|
||||
rowsRef: computed(() => rowsAndCols.value.rows),
|
||||
colsRef: computed(() => rowsAndCols.value.cols),
|
||||
hasEllpisisRef: computed(() => rowsAndCols.value.hasEllpisis),
|
||||
dataRelatedColsRef: computed(() => rowsAndCols.value.dataRelatedCols)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user