mirror of
https://github.com/element-plus/element-plus.git
synced 2026-03-13 07:51:17 +08:00
323 lines
8.2 KiB
Vue
323 lines
8.2 KiB
Vue
<template>
|
|
<div
|
|
ref="tableWrapper"
|
|
:class="[
|
|
{
|
|
[ns.m('fit')]: fit,
|
|
[ns.m('striped')]: stripe,
|
|
[ns.m('border')]: border || isGroup,
|
|
[ns.m('hidden')]: isHidden,
|
|
[ns.m('group')]: isGroup,
|
|
[ns.m('fluid-height')]: maxHeight,
|
|
[ns.m('scrollable-x')]: layout.scrollX.value,
|
|
[ns.m('scrollable-y')]: layout.scrollY.value,
|
|
[ns.m('enable-row-hover')]: !store.states.isComplex.value,
|
|
[ns.m('enable-row-transition')]:
|
|
(store.states.data.value || []).length !== 0 &&
|
|
(store.states.data.value || []).length < 100,
|
|
'has-footer': showSummary,
|
|
},
|
|
ns.m(tableSize),
|
|
className,
|
|
ns.b(),
|
|
ns.m(`layout-${tableLayout}`),
|
|
]"
|
|
:style="style"
|
|
:data-prefix="ns.namespace.value"
|
|
@mouseleave="handleMouseLeave()"
|
|
>
|
|
<div :class="ns.e('inner-wrapper')">
|
|
<div ref="hiddenColumns" class="hidden-columns">
|
|
<slot />
|
|
</div>
|
|
<div
|
|
v-if="showHeader && tableLayout === 'fixed'"
|
|
ref="headerWrapper"
|
|
v-mousewheel="handleHeaderFooterMousewheel"
|
|
:class="ns.e('header-wrapper')"
|
|
>
|
|
<table
|
|
ref="tableHeader"
|
|
:class="ns.e('header')"
|
|
:style="tableBodyStyles"
|
|
border="0"
|
|
cellpadding="0"
|
|
cellspacing="0"
|
|
>
|
|
<hColgroup
|
|
:columns="store.states.columns.value"
|
|
:table-layout="tableLayout"
|
|
/>
|
|
<table-header
|
|
ref="tableHeaderRef"
|
|
:border="border"
|
|
:default-sort="defaultSort"
|
|
:store="store"
|
|
@set-drag-visible="setDragVisible"
|
|
/>
|
|
</table>
|
|
</div>
|
|
<div ref="bodyWrapper" :style="bodyHeight" :class="ns.e('body-wrapper')">
|
|
<el-scrollbar
|
|
ref="scrollBarRef"
|
|
:height="maxHeight ? undefined : height"
|
|
:max-height="maxHeight ? height : undefined"
|
|
:view-style="scrollbarViewStyle"
|
|
:always="scrollbarAlwaysOn"
|
|
>
|
|
<table
|
|
ref="tableBody"
|
|
:class="ns.e('body')"
|
|
cellspacing="0"
|
|
cellpadding="0"
|
|
border="0"
|
|
:style="{
|
|
width: bodyWidth,
|
|
tableLayout,
|
|
}"
|
|
>
|
|
<hColgroup
|
|
:columns="store.states.columns.value"
|
|
:table-layout="tableLayout"
|
|
/>
|
|
<table-header
|
|
v-if="showHeader && tableLayout === 'auto'"
|
|
:border="border"
|
|
:default-sort="defaultSort"
|
|
:store="store"
|
|
@set-drag-visible="setDragVisible"
|
|
/>
|
|
<table-body
|
|
:context="context"
|
|
:highlight="highlightCurrentRow"
|
|
:row-class-name="rowClassName"
|
|
:tooltip-effect="tooltipEffect"
|
|
:row-style="rowStyle"
|
|
:store="store"
|
|
:stripe="stripe"
|
|
/>
|
|
</table>
|
|
<div
|
|
v-if="isEmpty"
|
|
ref="emptyBlock"
|
|
:style="emptyBlockStyle"
|
|
:class="ns.e('empty-block')"
|
|
>
|
|
<span :class="ns.e('empty-text')">
|
|
<slot name="empty">{{ computedEmptyText }}</slot>
|
|
</span>
|
|
</div>
|
|
<div
|
|
v-if="$slots.append"
|
|
ref="appendWrapper"
|
|
:class="ns.e('append-wrapper')"
|
|
>
|
|
<slot name="append" />
|
|
</div>
|
|
</el-scrollbar>
|
|
</div>
|
|
<div v-if="border || isGroup" :class="ns.e('border-left-patch')" />
|
|
</div>
|
|
<div
|
|
v-if="showSummary"
|
|
v-show="!isEmpty"
|
|
ref="footerWrapper"
|
|
v-mousewheel="handleHeaderFooterMousewheel"
|
|
:class="ns.e('footer-wrapper')"
|
|
>
|
|
<table-footer
|
|
:border="border"
|
|
:default-sort="defaultSort"
|
|
:store="store"
|
|
:style="tableBodyStyles"
|
|
:sum-text="computedSumText"
|
|
:summary-method="summaryMethod"
|
|
/>
|
|
</div>
|
|
<div
|
|
v-show="resizeProxyVisible"
|
|
ref="resizeProxy"
|
|
:class="ns.e('column-resize-proxy')"
|
|
/>
|
|
</div>
|
|
</template>
|
|
|
|
<script lang="ts">
|
|
import { computed, defineComponent, getCurrentInstance, provide } from 'vue'
|
|
import { debounce } from 'lodash-unified'
|
|
import { Mousewheel } from '@element-plus/directives'
|
|
import { useLocale, useNamespace } from '@element-plus/hooks'
|
|
import ElScrollbar from '@element-plus/components/scrollbar'
|
|
import { createStore } from './store/helper'
|
|
import TableLayout from './table-layout'
|
|
import TableHeader from './table-header'
|
|
import TableBody from './table-body'
|
|
import TableFooter from './table-footer'
|
|
import useUtils from './table/utils-helper'
|
|
import useStyle from './table/style-helper'
|
|
import defaultProps from './table/defaults'
|
|
import { TABLE_INJECTION_KEY } from './tokens'
|
|
import { hColgroup } from './h-helper'
|
|
import { useScrollbar } from './composables/use-scrollbar'
|
|
|
|
import type { Table } from './table/defaults'
|
|
|
|
let tableIdSeed = 1
|
|
export default defineComponent({
|
|
name: 'ElTable',
|
|
directives: {
|
|
Mousewheel,
|
|
},
|
|
components: {
|
|
TableHeader,
|
|
TableBody,
|
|
TableFooter,
|
|
ElScrollbar,
|
|
hColgroup,
|
|
},
|
|
props: defaultProps,
|
|
emits: [
|
|
'select',
|
|
'select-all',
|
|
'selection-change',
|
|
'cell-mouse-enter',
|
|
'cell-mouse-leave',
|
|
'cell-contextmenu',
|
|
'cell-click',
|
|
'cell-dblclick',
|
|
'row-click',
|
|
'row-contextmenu',
|
|
'row-dblclick',
|
|
'header-click',
|
|
'header-contextmenu',
|
|
'sort-change',
|
|
'filter-change',
|
|
'current-change',
|
|
'header-dragend',
|
|
'expand-change',
|
|
],
|
|
setup(props) {
|
|
type Row = typeof props.data[number]
|
|
const { t } = useLocale()
|
|
const ns = useNamespace('table')
|
|
const table = getCurrentInstance() as Table<Row>
|
|
provide(TABLE_INJECTION_KEY, table)
|
|
const store = createStore<Row>(table, props)
|
|
table.store = store
|
|
const layout = new TableLayout<Row>({
|
|
store: table.store,
|
|
table,
|
|
fit: props.fit,
|
|
showHeader: props.showHeader,
|
|
})
|
|
table.layout = layout
|
|
|
|
const isEmpty = computed(() => (store.states.data.value || []).length === 0)
|
|
|
|
/**
|
|
* open functions
|
|
*/
|
|
const {
|
|
setCurrentRow,
|
|
getSelectionRows,
|
|
toggleRowSelection,
|
|
clearSelection,
|
|
clearFilter,
|
|
toggleAllSelection,
|
|
toggleRowExpansion,
|
|
clearSort,
|
|
sort,
|
|
} = useUtils<Row>(store)
|
|
const {
|
|
isHidden,
|
|
renderExpanded,
|
|
setDragVisible,
|
|
isGroup,
|
|
handleMouseLeave,
|
|
handleHeaderFooterMousewheel,
|
|
tableSize,
|
|
bodyHeight,
|
|
height,
|
|
emptyBlockStyle,
|
|
handleFixedMousewheel,
|
|
fixedHeight,
|
|
fixedBodyHeight,
|
|
resizeProxyVisible,
|
|
bodyWidth,
|
|
resizeState,
|
|
doLayout,
|
|
tableBodyStyles,
|
|
tableLayout,
|
|
scrollbarViewStyle,
|
|
} = useStyle<Row>(props, layout, store, table)
|
|
|
|
const { scrollBarRef, scrollTo, setScrollLeft, setScrollTop } =
|
|
useScrollbar()
|
|
|
|
const debouncedUpdateLayout = debounce(doLayout, 50)
|
|
|
|
const tableId = `el-table_${tableIdSeed++}`
|
|
table.tableId = tableId
|
|
table.state = {
|
|
isGroup,
|
|
resizeState,
|
|
doLayout,
|
|
debouncedUpdateLayout,
|
|
}
|
|
const computedSumText = computed(
|
|
() => props.sumText || t('el.table.sumText')
|
|
)
|
|
|
|
const computedEmptyText = computed(() => {
|
|
return props.emptyText || t('el.table.emptyText')
|
|
})
|
|
|
|
return {
|
|
ns,
|
|
layout,
|
|
store,
|
|
handleHeaderFooterMousewheel,
|
|
handleMouseLeave,
|
|
tableId,
|
|
tableSize,
|
|
isHidden,
|
|
isEmpty,
|
|
renderExpanded,
|
|
resizeProxyVisible,
|
|
resizeState,
|
|
isGroup,
|
|
bodyWidth,
|
|
bodyHeight,
|
|
height,
|
|
tableBodyStyles,
|
|
emptyBlockStyle,
|
|
debouncedUpdateLayout,
|
|
handleFixedMousewheel,
|
|
fixedHeight,
|
|
fixedBodyHeight,
|
|
setCurrentRow,
|
|
getSelectionRows,
|
|
toggleRowSelection,
|
|
clearSelection,
|
|
clearFilter,
|
|
toggleAllSelection,
|
|
toggleRowExpansion,
|
|
clearSort,
|
|
doLayout,
|
|
sort,
|
|
t,
|
|
setDragVisible,
|
|
context: table,
|
|
computedSumText,
|
|
computedEmptyText,
|
|
tableLayout,
|
|
scrollbarViewStyle,
|
|
scrollBarRef,
|
|
scrollTo,
|
|
setScrollLeft,
|
|
setScrollTop,
|
|
}
|
|
},
|
|
})
|
|
</script>
|