mirror of
https://github.com/tusen-ai/naive-ui.git
synced 2025-01-30 12:52:43 +08:00
refactor(data-table): hoist fixed related status to base table from header
This commit is contained in:
parent
632a635bdd
commit
db6a7d79e7
@ -1,13 +1,15 @@
|
||||
<template>
|
||||
<div class="n-data-table-base-table">
|
||||
<table-header
|
||||
ref="headerRef"
|
||||
:placement="placement"
|
||||
:columns="columns"
|
||||
:data="data"
|
||||
:scroll-x="scrollX"
|
||||
@update:active-fixed-column="setActiveFixedColumn"
|
||||
/>
|
||||
<v-resize-observer @resize="handleHeaderResize">
|
||||
<table-header
|
||||
ref="headerRef"
|
||||
:placement="placement"
|
||||
:columns="columns"
|
||||
:data="data"
|
||||
:scroll-x="scrollX"
|
||||
@scroll="handleHeaderScroll"
|
||||
/>
|
||||
</v-resize-observer>
|
||||
<table-body
|
||||
ref="bodyRef"
|
||||
:style="bodyStyle"
|
||||
@ -24,17 +26,23 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { VResizeObserver } from 'vueuc'
|
||||
import { ref } from 'vue'
|
||||
import TableHeader from './TableParts/Header.vue'
|
||||
import TableBody from './TableParts/Body.vue'
|
||||
import resizeObserverDelegate from '../../_utils/delegate/resizeObserverDelegate'
|
||||
import formatLength from '../../_utils/css/formatLength'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
VResizeObserver,
|
||||
TableHeader,
|
||||
TableBody
|
||||
},
|
||||
provide () {
|
||||
return {
|
||||
NBaseTable: this
|
||||
}
|
||||
},
|
||||
inject: {
|
||||
NDataTable: {
|
||||
default: null
|
||||
@ -94,8 +102,11 @@ export default {
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
tableWidth: null,
|
||||
bodyMaxHeight: null,
|
||||
bodyMinHeight: null
|
||||
bodyMinHeight: null,
|
||||
leftActiveFixedColumn: {},
|
||||
rightActiveFixedColumn: {}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@ -104,37 +115,51 @@ export default {
|
||||
maxHeight: formatLength(this.bodyMaxHeight),
|
||||
minHeight: formatLength(this.bodyMinHeight)
|
||||
}
|
||||
},
|
||||
fixedColumnsLeft () {
|
||||
const columnsLeft = {}
|
||||
let left = 0
|
||||
let columns = this.columns
|
||||
columns.map((column) => {
|
||||
if (this.NDataTable.leftFixedColumns.indexOf(column) > -1) {
|
||||
columnsLeft[column.key] = left
|
||||
}
|
||||
left = left + this.headerRef.$refs[column.key].offsetWidth
|
||||
})
|
||||
return columnsLeft
|
||||
},
|
||||
fixedColumnsRight () {
|
||||
const columnsRight = {}
|
||||
let right = 0
|
||||
let columns = this.columns
|
||||
for (let i = columns.length - 1; i >= 0; i--) {
|
||||
if (this.NDataTable.rightFixedColumns.indexOf(this.columns[i]) > -1) {
|
||||
columnsRight[columns[i].key] = right
|
||||
}
|
||||
right = right + this.headerRef.$refs[columns[i].key].offsetWidth
|
||||
}
|
||||
return columnsRight
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
resizeObserverDelegate.registerHandler(
|
||||
this.getHeaderElement(),
|
||||
this.setBodyMinMaxHeight
|
||||
)
|
||||
this.setBodyMinMaxHeight()
|
||||
},
|
||||
beforeUnmount () {
|
||||
// BUG: beforeUnmount is called twice
|
||||
// wait for vue 3.0.1 to fix it
|
||||
resizeObserverDelegate.unregisterHandler(
|
||||
this.getHeaderElement()
|
||||
)
|
||||
},
|
||||
methods: {
|
||||
handleHeaderResize (entry) {
|
||||
this.setBodyMinMaxHeight(entry.contentRect.height)
|
||||
this.setActiveLeftFixedColumn(entry.target)
|
||||
this.setActiveRightFixedColumn(entry.target)
|
||||
},
|
||||
handleHeaderScroll (e) {
|
||||
this.setActiveRightFixedColumn(e.target)
|
||||
this.setActiveLeftFixedColumn(e.target)
|
||||
this.NDataTable.handleTableHeaderScroll(e)
|
||||
},
|
||||
getHeaderElement () {
|
||||
return this.headerRef.$el
|
||||
},
|
||||
getBodyElement () {
|
||||
return this.bodyRef.getScrollContainer()
|
||||
},
|
||||
setActiveFixedColumn (leftActiveFixedColumn, rightActiveFixedColumn) {
|
||||
const { bodyRef } = this
|
||||
bodyRef.activeLeft = leftActiveFixedColumn
|
||||
bodyRef.activeRight = rightActiveFixedColumn
|
||||
},
|
||||
setBodyMinMaxHeight () {
|
||||
setBodyMinMaxHeight (headerHeight) {
|
||||
const bordered = this.bordered
|
||||
const headerHeight = this.getHeaderElement().offsetHeight
|
||||
const maxHeight = this.maxHeight
|
||||
const minHeight = this.minHeight
|
||||
if (maxHeight !== null) {
|
||||
@ -143,6 +168,41 @@ export default {
|
||||
if (minHeight !== null) {
|
||||
this.bodyMinHeight = minHeight + (bordered ? -2 : 0) - headerHeight
|
||||
}
|
||||
},
|
||||
setActiveRightFixedColumn (target) {
|
||||
const rightFixedColumns = this.NDataTable.rightFixedColumns
|
||||
const scrollLeft = target.scrollLeft
|
||||
const tableWidth = this.tableWidth
|
||||
const scrollWidth = target.scrollWidth
|
||||
let rightWidth = 0
|
||||
const fixedColumnsRight = this.fixedColumnsRight
|
||||
const rightActiveFixedColumn = {}
|
||||
this.rightActiveFixedColumn = rightActiveFixedColumn
|
||||
for (let i = rightFixedColumns.length - 1; i >= 0; --i) {
|
||||
const key = rightFixedColumns[i].key
|
||||
if (scrollLeft + fixedColumnsRight[key] + tableWidth - rightWidth < scrollWidth) {
|
||||
this.rightActiveFixedColumn = { [key]: true }
|
||||
rightWidth += rightFixedColumns[i].width
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
},
|
||||
setActiveLeftFixedColumn (target) {
|
||||
const leftFixedColumns = this.NDataTable.leftFixedColumns
|
||||
const scrollLeft = target.scrollLeft
|
||||
let leftWidth = 0
|
||||
const fixedColumnsLeft = this.fixedColumnsLeft
|
||||
this.leftActiveFixedColumn = {}
|
||||
for (let i = 0; i < leftFixedColumns.length; ++i) {
|
||||
const key = leftFixedColumns[i].key
|
||||
if (scrollLeft > fixedColumnsLeft[key] - leftWidth) {
|
||||
this.leftActiveFixedColumn = { [key]: true }
|
||||
leftWidth += leftFixedColumns[i].width
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -44,8 +44,8 @@
|
||||
[`n-data-table-td--${column.align}-align`]: column.align,
|
||||
...(column.className && createClassObject(column.className)),
|
||||
[`n-data-table-td--fixed-${column.fixed}`]: column.width && column.fixed,
|
||||
'n-data-table-td--shadow-after': activeLeft[column.key],
|
||||
'n-data-table-td--shadow-before': activeRight[column.key],
|
||||
'n-data-table-td--shadow-after': NBaseTable.leftActiveFixedColumn[column.key],
|
||||
'n-data-table-td--shadow-before': NBaseTable.rightActiveFixedColumn[column.key],
|
||||
'n-data-table-td--selection': column.type === 'selection'
|
||||
}"
|
||||
>
|
||||
@ -84,6 +84,9 @@ export default {
|
||||
inject: {
|
||||
NDataTable: {
|
||||
default: null
|
||||
},
|
||||
NBaseTable: {
|
||||
default: null
|
||||
}
|
||||
},
|
||||
props: {
|
||||
@ -125,12 +128,6 @@ export default {
|
||||
scrollbarRef: ref(null)
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
activeLeft: {},
|
||||
activeRight: {}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
formatedScrollX () {
|
||||
return formatLength(this.scrollX)
|
||||
|
@ -5,7 +5,6 @@
|
||||
}"
|
||||
:style="headerStyle"
|
||||
class="n-data-table-base-table-header"
|
||||
@scroll="handleScroll"
|
||||
>
|
||||
<table
|
||||
ref="body"
|
||||
@ -37,8 +36,8 @@
|
||||
'n-data-table-th--filterable': isColumnFilterable(column),
|
||||
'n-data-table-th--sortable': isColumnSortable(column),
|
||||
[`n-data-table-th--fixed-${column.fixed}`]: column.fixed && column.width,
|
||||
'n-data-table-th--shadow-after': leftActiveFixedColumn[column.key],
|
||||
'n-data-table-th--shadow-before': rightActiveFixedColumn[column.key],
|
||||
'n-data-table-th--shadow-after': NBaseTable.leftActiveFixedColumn[column.key],
|
||||
'n-data-table-th--shadow-before': NBaseTable.rightActiveFixedColumn[column.key],
|
||||
'n-data-table-th--selection': column.type === 'selection'
|
||||
}"
|
||||
@click="handleHeaderClick($event, column)"
|
||||
@ -89,7 +88,6 @@ import SortButton from '../HeaderButton/SortButton.vue'
|
||||
import FilterButton from '../HeaderButton/FilterButton.vue'
|
||||
import { createCustomWidthStyle } from '../utils'
|
||||
import { render } from '../../../_utils/vue'
|
||||
import resizeObserverDelegate from '../../../_utils/delegate/resizeObserverDelegate'
|
||||
|
||||
function isColumnSortable (column) {
|
||||
return !!column.sorter
|
||||
@ -133,6 +131,9 @@ export default {
|
||||
inject: {
|
||||
NDataTable: {
|
||||
default: null
|
||||
},
|
||||
NBaseTable: {
|
||||
default: null
|
||||
}
|
||||
},
|
||||
props: {
|
||||
@ -151,17 +152,6 @@ export default {
|
||||
data: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
// eslint-disable-next-line vue/prop-name-casing
|
||||
'onUpdate:activeFixedColumn': {
|
||||
type: Function,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data: function () {
|
||||
return {
|
||||
leftActiveFixedColumn: [],
|
||||
rightActiveFixedColumn: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@ -187,61 +177,12 @@ export default {
|
||||
return {
|
||||
overflow: 'scroll'
|
||||
}
|
||||
},
|
||||
fixedColumnsLeft () {
|
||||
let columnsLeft = {}
|
||||
let left = 0
|
||||
let columns = this.columns
|
||||
columns.map((column) => {
|
||||
if (this.NDataTable.leftFixedColumns.indexOf(column) > -1) {
|
||||
columnsLeft[column.key] = left
|
||||
}
|
||||
left = left + this.$refs[column.key].offsetWidth
|
||||
})
|
||||
return columnsLeft
|
||||
},
|
||||
fixedColumnsRight () {
|
||||
let columnsRight = {}
|
||||
let right = 0
|
||||
let columns = this.columns
|
||||
for (let i = columns.length - 1; i >= 0; i--) {
|
||||
if (this.NDataTable.rightFixedColumns.indexOf(this.columns[i]) > -1) {
|
||||
columnsRight[columns[i].key] = right
|
||||
}
|
||||
right = right + this.$refs[columns[i].key].offsetWidth
|
||||
}
|
||||
return columnsRight
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
resizeObserverDelegate.registerHandler(this.$el, this.handleResize)
|
||||
this.handleResize()
|
||||
this.setActiveLeftFixedColumn(this.$el)
|
||||
this.setActiveRightFixedColumn(this.$el)
|
||||
this.doUpdateActiveFixedColumn(this.leftActiveFixedColumn, this.rightActiveFixedColumn)
|
||||
},
|
||||
beforeUnmount () {
|
||||
resizeObserverDelegate.unregisterHandler(this.$el)
|
||||
},
|
||||
methods: {
|
||||
doUpdateActiveFixedColumn (...args) {
|
||||
const {
|
||||
'onUpdate:activeFixedColumn': onUpdateActiveFixedColumn
|
||||
} = this
|
||||
onUpdateActiveFixedColumn(...args)
|
||||
},
|
||||
isColumnSortable,
|
||||
isColumnFilterable,
|
||||
createCustomWidthStyle,
|
||||
handleResize () {
|
||||
this.tableWidth = this.$el.offsetWidth
|
||||
},
|
||||
handleScroll (e) {
|
||||
this.setActiveRightFixedColumn(e.target)
|
||||
this.setActiveLeftFixedColumn(e.target)
|
||||
this.doUpdateActiveFixedColumn(this.leftActiveFixedColumn, this.rightActiveFixedColumn)
|
||||
this.NDataTable.handleTableHeaderScroll(e)
|
||||
},
|
||||
handleCheckboxInput (column) {
|
||||
if (this.checkboxIndererminate || this.checkboxChecked) {
|
||||
this.NDataTable.clearCheckAll(column)
|
||||
@ -258,41 +199,6 @@ export default {
|
||||
const activeSorter = this.NDataTable.syntheticActiveSorter
|
||||
const nextSorter = createNextSorter(column.key, activeSorter, column.sorter)
|
||||
this.NDataTable.changeSorter(nextSorter)
|
||||
},
|
||||
setActiveRightFixedColumn (target) {
|
||||
const rightFixedColumns = this.NDataTable.rightFixedColumns
|
||||
const scrollLeft = target.scrollLeft
|
||||
const tableWidth = this.tableWidth
|
||||
const scrollWidth = target.scrollWidth
|
||||
let rightWidth = 0
|
||||
const fixedColumnsRight = this.fixedColumnsRight
|
||||
const rightActiveFixedColumn = {}
|
||||
this.rightActiveFixedColumn = rightActiveFixedColumn
|
||||
for (let i = rightFixedColumns.length - 1; i >= 0; --i) {
|
||||
const key = rightFixedColumns[i].key
|
||||
if (scrollLeft + fixedColumnsRight[key] + tableWidth - rightWidth < scrollWidth) {
|
||||
this.rightActiveFixedColumn = { [key]: true }
|
||||
rightWidth += rightFixedColumns[i].width
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
},
|
||||
setActiveLeftFixedColumn (target) {
|
||||
const leftFixedColumns = this.NDataTable.leftFixedColumns
|
||||
const scrollLeft = target.scrollLeft
|
||||
let leftWidth = 0
|
||||
const fixedColumnsLeft = this.fixedColumnsLeft
|
||||
this.leftActiveFixedColumn = {}
|
||||
for (let i = 0; i < leftFixedColumns.length; ++i) {
|
||||
const key = leftFixedColumns[i].key
|
||||
if (scrollLeft > fixedColumnsLeft[key] - leftWidth) {
|
||||
this.leftActiveFixedColumn = { [key]: true }
|
||||
leftWidth += leftFixedColumns[i].width
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user