mirror of
https://gitee.com/element-plus/element-plus.git
synced 2024-12-12 12:25:22 +08:00
refactor(components): [el-table] use namespace (#5528)
This commit is contained in:
parent
dd5b84f885
commit
2f521c419c
@ -10,15 +10,13 @@
|
||||
</el-table-column>
|
||||
<el-table-column label="Name" width="180">
|
||||
<template #default="scope">
|
||||
<el-popover effect="light" trigger="hover" placement="top">
|
||||
<el-popover effect="light" trigger="hover" placement="top" width="auto">
|
||||
<template #default>
|
||||
<p>name: {{ scope.row.name }}</p>
|
||||
<p>address: {{ scope.row.address }}</p>
|
||||
<div>name: {{ scope.row.name }}</div>
|
||||
<div>address: {{ scope.row.address }}</div>
|
||||
</template>
|
||||
<template #reference>
|
||||
<div class="name-wrapper">
|
||||
<el-tag>{{ scope.row.name }}</el-tag>
|
||||
</div>
|
||||
</template>
|
||||
</el-popover>
|
||||
</template>
|
||||
|
@ -9,6 +9,11 @@ import type { TableColumnCtx } from './table-column/defaults'
|
||||
import type { Store } from './store'
|
||||
import type { TreeNode } from './table/defaults'
|
||||
|
||||
const defaultClassNames = {
|
||||
selection: 'table-column--selection',
|
||||
expand: 'table__expand-column',
|
||||
}
|
||||
|
||||
export const cellStarts = {
|
||||
default: {
|
||||
order: '',
|
||||
@ -18,7 +23,6 @@ export const cellStarts = {
|
||||
minWidth: 48,
|
||||
realWidth: 48,
|
||||
order: '',
|
||||
className: 'el-table-column--selection',
|
||||
},
|
||||
expand: {
|
||||
width: 48,
|
||||
@ -34,6 +38,10 @@ export const cellStarts = {
|
||||
},
|
||||
}
|
||||
|
||||
export const getDefaultClassName = (type) => {
|
||||
return defaultClassNames[type] || ''
|
||||
}
|
||||
|
||||
// 这些选项不应该被覆盖
|
||||
export const cellForced = {
|
||||
selection: {
|
||||
@ -105,9 +113,10 @@ export const cellForced = {
|
||||
return column.label || ''
|
||||
},
|
||||
renderCell<T>({ row, store }: { row: T; store: Store<T> }) {
|
||||
const classes = ['el-table__expand-icon']
|
||||
const { ns } = store
|
||||
const classes = [ns.e('expand-icon')]
|
||||
if (store.states.expandRows.value.indexOf(row) > -1) {
|
||||
classes.push('el-table__expand-icon--expanded')
|
||||
classes.push(ns.em('expand-icon', 'expanded'))
|
||||
}
|
||||
const callback = function (e: Event) {
|
||||
e.stopPropagation()
|
||||
@ -134,7 +143,6 @@ export const cellForced = {
|
||||
},
|
||||
sortable: false,
|
||||
resizable: false,
|
||||
className: 'el-table__expand-column',
|
||||
},
|
||||
}
|
||||
|
||||
@ -170,18 +178,19 @@ export function treeCellPrefix<T>({
|
||||
e.stopPropagation()
|
||||
store.loadOrToggle(row)
|
||||
}
|
||||
const { ns } = store
|
||||
if (treeNode.indent) {
|
||||
ele.push(
|
||||
h('span', {
|
||||
class: 'el-table__indent',
|
||||
class: ns.e('indent'),
|
||||
style: { 'padding-left': `${treeNode.indent}px` },
|
||||
})
|
||||
)
|
||||
}
|
||||
if (typeof treeNode.expanded === 'boolean' && !treeNode.noLazyChildren) {
|
||||
const expandClasses = [
|
||||
'el-table__expand-icon',
|
||||
treeNode.expanded ? 'el-table__expand-icon--expanded' : '',
|
||||
ns.e('expand-icon'),
|
||||
treeNode.expanded ? ns.em('expand-icon', 'expanded') : '',
|
||||
]
|
||||
let icon = ArrowRight
|
||||
if (treeNode.loading) {
|
||||
@ -200,7 +209,7 @@ export function treeCellPrefix<T>({
|
||||
return [
|
||||
h(
|
||||
ElIcon,
|
||||
{ class: { 'is-loading': treeNode.loading } },
|
||||
{ class: { [ns.is('loading')]: treeNode.loading } },
|
||||
{
|
||||
default: () => [h(icon)],
|
||||
}
|
||||
@ -213,7 +222,7 @@ export function treeCellPrefix<T>({
|
||||
} else {
|
||||
ele.push(
|
||||
h('span', {
|
||||
class: 'el-table__placeholder',
|
||||
class: ns.e('placeholder'),
|
||||
})
|
||||
)
|
||||
}
|
||||
|
@ -9,16 +9,16 @@
|
||||
append-to-body
|
||||
effect="light"
|
||||
pure
|
||||
popper-class="el-table-filter"
|
||||
:popper-class="ns.b()"
|
||||
persistent
|
||||
>
|
||||
<template #content>
|
||||
<div v-if="multiple">
|
||||
<div class="el-table-filter__content">
|
||||
<el-scrollbar wrap-class="el-table-filter__wrap">
|
||||
<div :class="ns.e('content')">
|
||||
<el-scrollbar :wrap-class="ns.e('wrap')">
|
||||
<el-checkbox-group
|
||||
v-model="filteredValue"
|
||||
class="el-table-filter__checkbox-group"
|
||||
:class="ns.e('checkbox-group')"
|
||||
>
|
||||
<el-checkbox
|
||||
v-for="filter in filters"
|
||||
@ -30,9 +30,9 @@
|
||||
</el-checkbox-group>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
<div class="el-table-filter__bottom">
|
||||
<div :class="ns.e('bottom')">
|
||||
<button
|
||||
:class="{ 'is-disabled': filteredValue.length === 0 }"
|
||||
:class="{ [ns.is('disabled')]: filteredValue.length === 0 }"
|
||||
:disabled="filteredValue.length === 0"
|
||||
type="button"
|
||||
@click="handleConfirm"
|
||||
@ -44,12 +44,15 @@
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<ul v-else class="el-table-filter__list">
|
||||
<ul v-else :class="ns.e('list')">
|
||||
<li
|
||||
:class="{
|
||||
'is-active': filterValue === undefined || filterValue === null,
|
||||
}"
|
||||
class="el-table-filter__list-item"
|
||||
:class="[
|
||||
ns.e('list-item'),
|
||||
{
|
||||
[ns.is('active')]:
|
||||
filterValue === undefined || filterValue === null,
|
||||
},
|
||||
]"
|
||||
@click="handleSelect(null)"
|
||||
>
|
||||
{{ t('el.table.clearFilter') }}
|
||||
@ -57,9 +60,8 @@
|
||||
<li
|
||||
v-for="filter in filters"
|
||||
:key="filter.value"
|
||||
:class="{ 'is-active': isActive(filter) }"
|
||||
:class="[ns.e('list-item'), ns.is('active', isActive(filter))]"
|
||||
:label="filter.value"
|
||||
class="el-table-filter__list-item"
|
||||
@click="handleSelect(filter.value)"
|
||||
>
|
||||
{{ filter.text }}
|
||||
@ -69,7 +71,10 @@
|
||||
<template #default>
|
||||
<span
|
||||
v-click-outside:[popperPaneRef]="hideFilterPanel"
|
||||
class="el-table__column-filter-trigger el-none-outline"
|
||||
:class="[
|
||||
`${ns.namespace.value}-table__column-filter-trigger`,
|
||||
`${ns.namespace.value}-none-outline`,
|
||||
]"
|
||||
@click="showFilterPanel"
|
||||
>
|
||||
<el-icon>
|
||||
@ -87,7 +92,7 @@ import ElCheckbox from '@element-plus/components/checkbox'
|
||||
import { ElIcon } from '@element-plus/components/icon'
|
||||
import { ArrowDown, ArrowUp } from '@element-plus/icons-vue'
|
||||
import { ClickOutside } from '@element-plus/directives'
|
||||
import { useLocale } from '@element-plus/hooks'
|
||||
import { useLocale, useNamespace } from '@element-plus/hooks'
|
||||
import ElTooltip from '@element-plus/components/tooltip'
|
||||
import ElScrollbar from '@element-plus/components/scrollbar'
|
||||
import type { Placement } from '@element-plus/components/popper'
|
||||
@ -129,7 +134,8 @@ export default defineComponent({
|
||||
setup(props) {
|
||||
const instance = getCurrentInstance()
|
||||
const { t } = useLocale()
|
||||
const parent = instance.parent as TableHeader
|
||||
const ns = useNamespace('table-filter')
|
||||
const parent = instance?.parent as TableHeader
|
||||
if (!parent.filterPanels.value[props.column.id]) {
|
||||
parent.filterPanels.value[props.column.id] = instance
|
||||
}
|
||||
@ -139,7 +145,7 @@ export default defineComponent({
|
||||
return props.column && props.column.filters
|
||||
})
|
||||
const filterValue = computed({
|
||||
get: () => (props.column.filteredValue || [])[0],
|
||||
get: () => (props.column?.filteredValue || [])[0],
|
||||
set: (value: string) => {
|
||||
if (filteredValue.value) {
|
||||
if (typeof value !== 'undefined' && value !== null) {
|
||||
@ -235,6 +241,7 @@ export default defineComponent({
|
||||
handleSelect,
|
||||
isActive,
|
||||
t,
|
||||
ns,
|
||||
showFilterPanel,
|
||||
hideFilterPanel,
|
||||
popperPaneRef,
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { nextTick, getCurrentInstance, unref } from 'vue'
|
||||
import { useNamespace } from '@element-plus/hooks'
|
||||
import useWatcher from './watcher'
|
||||
|
||||
import type { Ref } from 'vue'
|
||||
@ -37,6 +38,7 @@ function sortColumn<T>(array: TableColumnCtx<T>[]) {
|
||||
function useStore<T>() {
|
||||
const instance = getCurrentInstance() as Table<T>
|
||||
const watcher = useWatcher<T>()
|
||||
const ns = useNamespace('table')
|
||||
type StoreStates = typeof watcher.states
|
||||
const mutations = {
|
||||
setData(states: StoreStates, data: T[]) {
|
||||
@ -200,6 +202,7 @@ function useStore<T>() {
|
||||
nextTick(() => instance.layout.updateScrollY.apply(instance.layout))
|
||||
}
|
||||
return {
|
||||
ns,
|
||||
...watcher,
|
||||
mutations,
|
||||
commit,
|
||||
|
@ -14,18 +14,20 @@ function useEvents<T>(props: Partial<TableBodyProps<T>>) {
|
||||
const table = parent
|
||||
const cell = getCell(event)
|
||||
let column: TableColumnCtx<T>
|
||||
const namespace = table?.vnode.el?.dataset.prefix
|
||||
if (cell) {
|
||||
column = getColumnByCell(
|
||||
{
|
||||
columns: props.store.states.columns.value,
|
||||
},
|
||||
cell
|
||||
cell,
|
||||
namespace
|
||||
)
|
||||
if (column) {
|
||||
table.emit(`cell-${name}`, row, column, cell, event)
|
||||
table?.emit(`cell-${name}`, row, column, cell, event)
|
||||
}
|
||||
}
|
||||
table.emit(`row-${name}`, row, column, event)
|
||||
table?.emit(`row-${name}`, row, column, event)
|
||||
}
|
||||
const handleDoubleClick = (event: Event, row: T) => {
|
||||
handleEvent(event, row, 'dblclick')
|
||||
@ -49,16 +51,17 @@ function useEvents<T>(props: Partial<TableBodyProps<T>>) {
|
||||
) => {
|
||||
const table = parent
|
||||
const cell = getCell(event)
|
||||
|
||||
const namespace = table?.vnode.el?.dataset.prefix
|
||||
if (cell) {
|
||||
const column = getColumnByCell(
|
||||
{
|
||||
columns: props.store.states.columns.value,
|
||||
},
|
||||
cell
|
||||
cell,
|
||||
namespace
|
||||
)
|
||||
const hoverState = (table.hoverState = { cell, column, row })
|
||||
table.emit(
|
||||
table?.emit(
|
||||
'cell-mouse-enter',
|
||||
hoverState.row,
|
||||
hoverState.column,
|
||||
@ -71,7 +74,12 @@ function useEvents<T>(props: Partial<TableBodyProps<T>>) {
|
||||
const cellChild = (event.target as HTMLElement).querySelector(
|
||||
'.cell'
|
||||
) as HTMLElement
|
||||
if (!(hasClass(cellChild, 'el-tooltip') && cellChild.childNodes.length)) {
|
||||
if (
|
||||
!(
|
||||
hasClass(cellChild, `${namespace}-tooltip`) &&
|
||||
cellChild.childNodes.length
|
||||
)
|
||||
) {
|
||||
return
|
||||
}
|
||||
// use range width instead of scrollWidth to determine whether the text is overflowing
|
||||
@ -102,8 +110,8 @@ function useEvents<T>(props: Partial<TableBodyProps<T>>) {
|
||||
const cell = getCell(event)
|
||||
if (!cell) return
|
||||
|
||||
const oldHoverState = parent.hoverState
|
||||
parent.emit(
|
||||
const oldHoverState = parent?.hoverState
|
||||
parent?.emit(
|
||||
'cell-mouse-leave',
|
||||
oldHoverState?.row,
|
||||
oldHoverState?.column,
|
||||
|
@ -9,6 +9,7 @@ import {
|
||||
} from 'vue'
|
||||
import { isClient } from '@vueuse/core'
|
||||
import { addClass, removeClass } from '@element-plus/utils/dom'
|
||||
import { useNamespace } from '@element-plus/hooks'
|
||||
import { hColgroup } from '../h-helper'
|
||||
import useLayoutObserver from '../layout-observer'
|
||||
import { removePopper } from '../util'
|
||||
@ -24,9 +25,10 @@ export default defineComponent({
|
||||
setup(props) {
|
||||
const instance = getCurrentInstance()
|
||||
const parent = inject(TABLE_INJECTION_KEY)
|
||||
const ns = useNamespace('table')
|
||||
const { wrappedRowRender, tooltipContent, tooltipTrigger } =
|
||||
useRender(props)
|
||||
const { onColumnsChange, onScrollableChange } = useLayoutObserver(parent)
|
||||
const { onColumnsChange, onScrollableChange } = useLayoutObserver(parent!)
|
||||
|
||||
watch(props.store.states.hoverRow, (newVal: any, oldVal: any) => {
|
||||
if (!props.store.states.isComplex.value || !isClient) return
|
||||
@ -35,7 +37,7 @@ export default defineComponent({
|
||||
raf = (fn) => window.setTimeout(fn, 16)
|
||||
}
|
||||
raf(() => {
|
||||
const rows = instance.vnode.el.querySelectorAll('.el-table__row')
|
||||
const rows = instance?.vnode.el?.querySelectorAll(ns.e('row'))
|
||||
const oldRow = rows[oldVal]
|
||||
const newRow = rows[newVal]
|
||||
if (oldRow) {
|
||||
@ -55,6 +57,7 @@ export default defineComponent({
|
||||
})
|
||||
|
||||
return {
|
||||
ns,
|
||||
onColumnsChange,
|
||||
onScrollableChange,
|
||||
wrappedRowRender,
|
||||
@ -63,13 +66,13 @@ export default defineComponent({
|
||||
}
|
||||
},
|
||||
render() {
|
||||
const { wrappedRowRender, store } = this
|
||||
const { ns, wrappedRowRender, store } = this
|
||||
const data = store.states.data.value || []
|
||||
const columns = store.states.columns.value
|
||||
return h(
|
||||
'table',
|
||||
{
|
||||
class: 'el-table__body',
|
||||
class: ns.e('body'),
|
||||
cellspacing: '0',
|
||||
cellpadding: '0',
|
||||
border: '0',
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { inject } from 'vue'
|
||||
import { useNamespace } from '@element-plus/hooks'
|
||||
import {
|
||||
getFixedColumnOffset,
|
||||
getFixedColumnsClass,
|
||||
@ -10,9 +11,10 @@ import type { TableBodyProps } from './defaults'
|
||||
|
||||
function useStyles<T>(props: Partial<TableBodyProps<T>>) {
|
||||
const parent = inject(TABLE_INJECTION_KEY)
|
||||
const ns = useNamespace('table')
|
||||
|
||||
const getRowStyle = (row: T, rowIndex: number) => {
|
||||
const rowStyle = parent.props.rowStyle
|
||||
const rowStyle = parent?.props.rowStyle
|
||||
if (typeof rowStyle === 'function') {
|
||||
return rowStyle.call(null, {
|
||||
row,
|
||||
@ -23,18 +25,18 @@ function useStyles<T>(props: Partial<TableBodyProps<T>>) {
|
||||
}
|
||||
|
||||
const getRowClass = (row: T, rowIndex: number) => {
|
||||
const classes = ['el-table__row']
|
||||
const classes = [ns.e('row')]
|
||||
if (
|
||||
parent.props.highlightCurrentRow &&
|
||||
parent?.props.highlightCurrentRow &&
|
||||
row === props.store.states.currentRow.value
|
||||
) {
|
||||
classes.push('current-row')
|
||||
}
|
||||
|
||||
if (props.stripe && rowIndex % 2 === 1) {
|
||||
classes.push('el-table__row--striped')
|
||||
classes.push(ns.em('row', 'striped'))
|
||||
}
|
||||
const rowClassName = parent.props.rowClassName
|
||||
const rowClassName = parent?.props.rowClassName
|
||||
if (typeof rowClassName === 'string') {
|
||||
classes.push(rowClassName)
|
||||
} else if (typeof rowClassName === 'function') {
|
||||
@ -59,7 +61,7 @@ function useStyles<T>(props: Partial<TableBodyProps<T>>) {
|
||||
row: T,
|
||||
column: TableColumnCtx<T>
|
||||
) => {
|
||||
const cellStyle = parent.props.cellStyle
|
||||
const cellStyle = parent?.props.cellStyle
|
||||
let cellStyles = cellStyle ?? {}
|
||||
if (typeof cellStyle === 'function') {
|
||||
cellStyles = cellStyle.call(null, {
|
||||
@ -71,7 +73,7 @@ function useStyles<T>(props: Partial<TableBodyProps<T>>) {
|
||||
}
|
||||
const fixedStyle = getFixedColumnOffset(
|
||||
columnIndex,
|
||||
props.fixed,
|
||||
props?.fixed,
|
||||
props.store
|
||||
)
|
||||
ensurePosition(fixedStyle, 'left')
|
||||
@ -87,9 +89,9 @@ function useStyles<T>(props: Partial<TableBodyProps<T>>) {
|
||||
) => {
|
||||
const fixedClasses = column.isSubColumn
|
||||
? []
|
||||
: getFixedColumnsClass(columnIndex, props.fixed, props.store)
|
||||
: getFixedColumnsClass(ns.b(), columnIndex, props?.fixed, props.store)
|
||||
const classes = [column.id, column.align, column.className, ...fixedClasses]
|
||||
const cellClassName = parent.props.cellClassName
|
||||
const cellClassName = parent?.props.cellClassName
|
||||
if (typeof cellClassName === 'string') {
|
||||
classes.push(cellClassName)
|
||||
} else if (typeof cellClassName === 'function') {
|
||||
@ -102,9 +104,7 @@ function useStyles<T>(props: Partial<TableBodyProps<T>>) {
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
classes.push('el-table__cell')
|
||||
|
||||
classes.push(ns.e('cell'))
|
||||
return classes.join(' ')
|
||||
}
|
||||
const getSpan = (
|
||||
@ -115,7 +115,7 @@ function useStyles<T>(props: Partial<TableBodyProps<T>>) {
|
||||
) => {
|
||||
let rowspan = 1
|
||||
let colspan = 1
|
||||
const fn = parent.props.spanMethod
|
||||
const fn = parent?.props.spanMethod
|
||||
if (typeof fn === 'function') {
|
||||
const result = fn({
|
||||
row,
|
||||
|
@ -1,6 +1,12 @@
|
||||
import { getCurrentInstance, h, ref, computed, watchEffect } from 'vue'
|
||||
import { getCurrentInstance, h, ref, computed, watchEffect, unref } from 'vue'
|
||||
import { debugWarn } from '@element-plus/utils/error'
|
||||
import { cellForced, defaultRenderCell, treeCellPrefix } from '../config'
|
||||
import { useNamespace } from '@element-plus/hooks'
|
||||
import {
|
||||
cellForced,
|
||||
defaultRenderCell,
|
||||
treeCellPrefix,
|
||||
getDefaultClassName,
|
||||
} from '../config'
|
||||
import { parseWidth, parseMinWidth } from '../util'
|
||||
|
||||
import type { ComputedRef } from 'vue'
|
||||
@ -16,6 +22,7 @@ function useRender<T>(
|
||||
const isSubColumn = ref(false)
|
||||
const realAlign = ref<string>()
|
||||
const realHeaderAlign = ref<string>()
|
||||
const ns = useNamespace('table')
|
||||
watchEffect(() => {
|
||||
realAlign.value = props.align ? `is-${props.align}` : null
|
||||
// nextline help render
|
||||
@ -57,10 +64,17 @@ function useRender<T>(
|
||||
const source = cellForced[type] || {}
|
||||
Object.keys(source).forEach((prop) => {
|
||||
const value = source[prop]
|
||||
if (value !== undefined) {
|
||||
column[prop] = prop === 'className' ? `${column[prop]} ${value}` : value
|
||||
if (prop !== 'className' && value !== undefined) {
|
||||
column[prop] = value
|
||||
}
|
||||
})
|
||||
const className = getDefaultClassName(type)
|
||||
if (className) {
|
||||
const forceClass = `${unref(ns.namespace)}-${className}`
|
||||
column.className = column.className
|
||||
? `${column.className} ${forceClass}`
|
||||
: forceClass
|
||||
}
|
||||
return column
|
||||
}
|
||||
|
||||
@ -123,7 +137,7 @@ function useRender<T>(
|
||||
style: {},
|
||||
}
|
||||
if (column.showOverflowTooltip) {
|
||||
props.class += ' el-tooltip'
|
||||
props.class = `${props.class} ${unref(ns.namespace)}-tooltip`
|
||||
props.style = {
|
||||
width: `${
|
||||
(data.column.realWidth || Number(data.column.width)) - 1
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { defineComponent, h } from 'vue'
|
||||
import { useNamespace } from '@element-plus/hooks'
|
||||
import { hColgroup } from '../h-helper'
|
||||
import useStyle from './style-helper'
|
||||
import type { Store } from '../store'
|
||||
@ -45,15 +46,23 @@ export default defineComponent({
|
||||
const { getCellClasses, getCellStyles, columns } = useStyle(
|
||||
props as TableFooter<DefaultRow>
|
||||
)
|
||||
const ns = useNamespace('table')
|
||||
return {
|
||||
ns,
|
||||
getCellClasses,
|
||||
getCellStyles,
|
||||
columns,
|
||||
}
|
||||
},
|
||||
render() {
|
||||
const { columns, getCellStyles, getCellClasses, summaryMethod, sumText } =
|
||||
this
|
||||
const {
|
||||
columns,
|
||||
getCellStyles,
|
||||
getCellClasses,
|
||||
summaryMethod,
|
||||
sumText,
|
||||
ns,
|
||||
} = this
|
||||
const data = this.store.states.data.value
|
||||
let sums = []
|
||||
if (summaryMethod) {
|
||||
@ -95,7 +104,7 @@ export default defineComponent({
|
||||
return h(
|
||||
'table',
|
||||
{
|
||||
class: 'el-table__footer',
|
||||
class: ns.e('footer'),
|
||||
cellspacing: '0',
|
||||
cellpadding: '0',
|
||||
border: '0',
|
||||
|
@ -1,11 +1,9 @@
|
||||
import { computed, getCurrentInstance } from 'vue'
|
||||
import { computed, inject } from 'vue'
|
||||
import { TABLE_INJECTION_KEY } from '../tokens'
|
||||
|
||||
import type { Table } from '../table/defaults'
|
||||
|
||||
function useMapState<T>() {
|
||||
const instance = getCurrentInstance()
|
||||
const table = instance.parent as Table<T>
|
||||
const store = table.store
|
||||
function useMapState() {
|
||||
const table = inject(TABLE_INJECTION_KEY)
|
||||
const store = table?.store
|
||||
const leftFixedLeafCount = computed(() => {
|
||||
return store.states.fixedLeafColumnsLength.value
|
||||
})
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { useNamespace } from '@element-plus/hooks'
|
||||
import {
|
||||
getFixedColumnOffset,
|
||||
getFixedColumnsClass,
|
||||
@ -8,22 +9,23 @@ import type { TableColumnCtx } from '../table-column/defaults'
|
||||
import type { TableFooter } from '.'
|
||||
|
||||
function useStyle<T>(props: TableFooter<T>) {
|
||||
const { columns } = useMapState<T>()
|
||||
const { columns } = useMapState()
|
||||
const ns = useNamespace('table')
|
||||
|
||||
const getCellClasses = (columns: TableColumnCtx<T>[], cellIndex: number) => {
|
||||
const column = columns[cellIndex]
|
||||
const classes = [
|
||||
'el-table__cell',
|
||||
ns.e('cell'),
|
||||
column.id,
|
||||
column.align,
|
||||
column.labelClassName,
|
||||
...getFixedColumnsClass(cellIndex, column.fixed, props.store),
|
||||
...getFixedColumnsClass(ns.b(), cellIndex, column.fixed, props.store),
|
||||
]
|
||||
if (column.className) {
|
||||
classes.push(column.className)
|
||||
}
|
||||
if (!column.children) {
|
||||
classes.push('is-leaf')
|
||||
classes.push(ns.is('leaf'))
|
||||
}
|
||||
return classes
|
||||
}
|
||||
|
@ -1,14 +1,13 @@
|
||||
import { getCurrentInstance, ref } from 'vue'
|
||||
import { getCurrentInstance, ref, inject } from 'vue'
|
||||
import { isClient } from '@vueuse/core'
|
||||
import { hasClass, addClass, removeClass } from '@element-plus/utils/dom'
|
||||
|
||||
import { TABLE_INJECTION_KEY } from '../tokens'
|
||||
import type { TableHeaderProps } from '.'
|
||||
import type { TableColumnCtx } from '../table-column/defaults'
|
||||
import type { Table } from '../table/defaults'
|
||||
|
||||
function useEvent<T>(props: TableHeaderProps<T>, emit) {
|
||||
const instance = getCurrentInstance()
|
||||
const parent = instance.parent as Table<T>
|
||||
const parent = inject(TABLE_INJECTION_KEY)
|
||||
const handleFilterClick = (event: Event) => {
|
||||
event.stopPropagation()
|
||||
return
|
||||
@ -20,11 +19,11 @@ function useEvent<T>(props: TableHeaderProps<T>, emit) {
|
||||
} else if (column.filterable && !column.sortable) {
|
||||
handleFilterClick(event)
|
||||
}
|
||||
parent.emit('header-click', column, event)
|
||||
parent?.emit('header-click', column, event)
|
||||
}
|
||||
|
||||
const handleHeaderContextMenu = (event: Event, column: TableColumnCtx<T>) => {
|
||||
parent.emit('header-contextmenu', column, event)
|
||||
parent?.emit('header-contextmenu', column, event)
|
||||
}
|
||||
const draggingColumn = ref(null)
|
||||
const dragging = ref(false)
|
||||
@ -38,7 +37,7 @@ function useEvent<T>(props: TableHeaderProps<T>, emit) {
|
||||
|
||||
const table = parent
|
||||
emit('set-drag-visible', true)
|
||||
const tableEl = table.vnode.el
|
||||
const tableEl = table?.vnode.el
|
||||
const tableLeft = tableEl.getBoundingClientRect().left
|
||||
const columnEl = instance.vnode.el.querySelector(`th.${column.id}`)
|
||||
const columnRect = columnEl.getBoundingClientRect()
|
||||
@ -52,7 +51,7 @@ function useEvent<T>(props: TableHeaderProps<T>, emit) {
|
||||
startColumnLeft: columnRect.left - tableLeft,
|
||||
tableLeft,
|
||||
}
|
||||
const resizeProxy = table.refs.resizeProxy as HTMLElement
|
||||
const resizeProxy = table?.refs.resizeProxy as HTMLElement
|
||||
resizeProxy.style.left = `${(dragState.value as any).startLeft}px`
|
||||
|
||||
document.onselectstart = function () {
|
||||
@ -76,7 +75,7 @@ function useEvent<T>(props: TableHeaderProps<T>, emit) {
|
||||
const finalLeft = parseInt(resizeProxy.style.left, 10)
|
||||
const columnWidth = finalLeft - startColumnLeft
|
||||
column.width = column.realWidth = columnWidth
|
||||
table.emit(
|
||||
table?.emit(
|
||||
'header-dragend',
|
||||
column.width,
|
||||
startLeft - startColumnLeft,
|
||||
@ -193,7 +192,7 @@ function useEvent<T>(props: TableHeaderProps<T>, emit) {
|
||||
states.sortProp.value = sortProp
|
||||
states.sortOrder.value = sortOrder
|
||||
|
||||
parent.store.commit('changeSortCondition')
|
||||
parent?.store.commit('changeSortCondition')
|
||||
}
|
||||
|
||||
return {
|
||||
|
@ -5,17 +5,19 @@ import {
|
||||
nextTick,
|
||||
ref,
|
||||
h,
|
||||
inject,
|
||||
} from 'vue'
|
||||
import ElCheckbox from '@element-plus/components/checkbox'
|
||||
import { useNamespace } from '@element-plus/hooks'
|
||||
import FilterPanel from '../filter-panel.vue'
|
||||
import useLayoutObserver from '../layout-observer'
|
||||
import { hColgroup } from '../h-helper'
|
||||
import { TABLE_INJECTION_KEY } from '../tokens'
|
||||
import useEvent from './event-helper'
|
||||
import useStyle from './style.helper'
|
||||
import useUtils from './utils-helper'
|
||||
|
||||
import type { ComponentInternalInstance, Ref, PropType } from 'vue'
|
||||
import type { DefaultRow, Sort, Table } from '../table/defaults'
|
||||
import type { DefaultRow, Sort } from '../table/defaults'
|
||||
import type { Store } from '../store'
|
||||
export interface TableHeader extends ComponentInternalInstance {
|
||||
state: {
|
||||
@ -58,15 +60,16 @@ export default defineComponent({
|
||||
},
|
||||
setup(props, { emit }) {
|
||||
const instance = getCurrentInstance() as TableHeader
|
||||
const parent = instance.parent as Table<unknown>
|
||||
const storeData = parent.store.states
|
||||
const parent = inject(TABLE_INJECTION_KEY)
|
||||
const ns = useNamespace('table')
|
||||
const storeData = parent?.store.states
|
||||
const filterPanels = ref({})
|
||||
const { onColumnsChange, onScrollableChange } = useLayoutObserver(parent)
|
||||
const { onColumnsChange, onScrollableChange } = useLayoutObserver(parent!)
|
||||
onMounted(() => {
|
||||
nextTick(() => {
|
||||
const { prop, order } = props.defaultSort
|
||||
const init = true
|
||||
parent.store.commit('sort', { prop, order, init })
|
||||
parent?.store.commit('sort', { prop, order, init })
|
||||
})
|
||||
})
|
||||
const {
|
||||
@ -96,6 +99,7 @@ export default defineComponent({
|
||||
instance.filterPanels = filterPanels
|
||||
|
||||
return {
|
||||
ns,
|
||||
columns: storeData.columns,
|
||||
filterPanels,
|
||||
onColumnsChange,
|
||||
@ -118,6 +122,7 @@ export default defineComponent({
|
||||
},
|
||||
render() {
|
||||
const {
|
||||
ns,
|
||||
columns,
|
||||
isGroup,
|
||||
columnRows,
|
||||
@ -141,14 +146,14 @@ export default defineComponent({
|
||||
border: '0',
|
||||
cellpadding: '0',
|
||||
cellspacing: '0',
|
||||
class: 'el-table__header',
|
||||
class: ns.e('header'),
|
||||
},
|
||||
[
|
||||
hColgroup(columns),
|
||||
h(
|
||||
'thead',
|
||||
{
|
||||
class: { 'is-group': isGroup },
|
||||
class: { [ns.is('group')]: isGroup },
|
||||
},
|
||||
columnRows.map((subColumns, rowIndex) =>
|
||||
h(
|
||||
|
@ -1,19 +1,20 @@
|
||||
import { getCurrentInstance } from 'vue'
|
||||
import { inject } from 'vue'
|
||||
import { useNamespace } from '@element-plus/hooks'
|
||||
import {
|
||||
getFixedColumnsClass,
|
||||
getFixedColumnOffset,
|
||||
ensurePosition,
|
||||
} from '../util'
|
||||
import { TABLE_INJECTION_KEY } from '../tokens'
|
||||
import type { TableColumnCtx } from '../table-column/defaults'
|
||||
import type { Table } from '../table/defaults'
|
||||
import type { TableHeaderProps } from '.'
|
||||
|
||||
function useStyle<T>(props: TableHeaderProps<T>) {
|
||||
const instance = getCurrentInstance()
|
||||
const parent = instance.parent as Table<T>
|
||||
const parent = inject(TABLE_INJECTION_KEY)
|
||||
const ns = useNamespace('table')
|
||||
|
||||
const getHeaderRowStyle = (rowIndex: number) => {
|
||||
const headerRowStyle = parent.props.headerRowStyle
|
||||
const headerRowStyle = parent?.props.headerRowStyle
|
||||
if (typeof headerRowStyle === 'function') {
|
||||
return headerRowStyle.call(null, { rowIndex })
|
||||
}
|
||||
@ -21,8 +22,8 @@ function useStyle<T>(props: TableHeaderProps<T>) {
|
||||
}
|
||||
|
||||
const getHeaderRowClass = (rowIndex: number): string => {
|
||||
const classes = []
|
||||
const headerRowClassName = parent.props.headerRowClassName
|
||||
const classes: string[] = []
|
||||
const headerRowClassName = parent?.props.headerRowClassName
|
||||
if (typeof headerRowClassName === 'string') {
|
||||
classes.push(headerRowClassName)
|
||||
} else if (typeof headerRowClassName === 'function') {
|
||||
@ -38,7 +39,7 @@ function useStyle<T>(props: TableHeaderProps<T>) {
|
||||
row: T,
|
||||
column: TableColumnCtx<T>
|
||||
) => {
|
||||
let headerCellStyles = parent.props.headerCellStyle ?? {}
|
||||
let headerCellStyles = parent?.props.headerCellStyle ?? {}
|
||||
if (typeof headerCellStyles === 'function') {
|
||||
headerCellStyles = headerCellStyles.call(null, {
|
||||
rowIndex,
|
||||
@ -67,6 +68,7 @@ function useStyle<T>(props: TableHeaderProps<T>) {
|
||||
const fixedClasses = column.isSubColumn
|
||||
? []
|
||||
: getFixedColumnsClass<T>(
|
||||
ns.b(),
|
||||
columnIndex,
|
||||
column.fixed,
|
||||
props.store,
|
||||
@ -89,7 +91,7 @@ function useStyle<T>(props: TableHeaderProps<T>) {
|
||||
classes.push('is-sortable')
|
||||
}
|
||||
|
||||
const headerCellClassName = parent.props.headerCellClassName
|
||||
const headerCellClassName = parent?.props.headerCellClassName
|
||||
if (typeof headerCellClassName === 'string') {
|
||||
classes.push(headerCellClassName)
|
||||
} else if (typeof headerCellClassName === 'function') {
|
||||
@ -103,7 +105,7 @@ function useStyle<T>(props: TableHeaderProps<T>) {
|
||||
)
|
||||
}
|
||||
|
||||
classes.push('el-table__cell')
|
||||
classes.push(ns.e('cell'))
|
||||
|
||||
return classes.join(' ')
|
||||
}
|
||||
|
@ -1,13 +1,12 @@
|
||||
import { getCurrentInstance, computed } from 'vue'
|
||||
|
||||
import { computed, inject } from 'vue'
|
||||
import { TABLE_INJECTION_KEY } from '../tokens'
|
||||
import type { TableColumnCtx } from '../table-column/defaults'
|
||||
import type { Table } from '../table/defaults'
|
||||
import type { TableHeaderProps } from '.'
|
||||
|
||||
const getAllColumns = <T>(
|
||||
columns: TableColumnCtx<T>[]
|
||||
): TableColumnCtx<T>[] => {
|
||||
const result = []
|
||||
const result: TableColumnCtx<T>[] = []
|
||||
columns.forEach((column) => {
|
||||
if (column.children) {
|
||||
result.push(column)
|
||||
@ -53,7 +52,7 @@ const convertToRows = <T>(
|
||||
rows.push([])
|
||||
}
|
||||
|
||||
const allColumns = getAllColumns(originColumns)
|
||||
const allColumns: TableColumnCtx<T>[] = getAllColumns(originColumns)
|
||||
|
||||
allColumns.forEach((column) => {
|
||||
if (!column.children) {
|
||||
@ -69,19 +68,20 @@ const convertToRows = <T>(
|
||||
}
|
||||
|
||||
function useUtils<T>(props: TableHeaderProps<T>) {
|
||||
const instance = getCurrentInstance()
|
||||
const parent = instance.parent as Table<T>
|
||||
const parent = inject(TABLE_INJECTION_KEY)
|
||||
const columnRows = computed(() => {
|
||||
return convertToRows(props.store.states.originColumns.value)
|
||||
})
|
||||
const isGroup = computed(() => {
|
||||
const result = columnRows.value.length > 1
|
||||
if (result) parent.state.isGroup.value = true
|
||||
if (result && parent) {
|
||||
parent.state.isGroup.value = true
|
||||
}
|
||||
return result
|
||||
})
|
||||
const toggleAllSelection = (event: Event) => {
|
||||
event.stopPropagation()
|
||||
parent.store.commit('toggleAllSelection')
|
||||
parent?.store.commit('toggleAllSelection')
|
||||
}
|
||||
return {
|
||||
isGroup,
|
||||
|
@ -136,14 +136,16 @@ class TableLayout<T> {
|
||||
|
||||
updateElsHeight() {
|
||||
if (!this.table.$ready) return nextTick(() => this.updateElsHeight())
|
||||
const { headerWrapper, appendWrapper, footerWrapper, bodyWrapper } =
|
||||
this.table.refs
|
||||
const {
|
||||
headerWrapper,
|
||||
appendWrapper,
|
||||
footerWrapper,
|
||||
tableHeader,
|
||||
tableBody,
|
||||
} = this.table.refs
|
||||
this.appendHeight.value = appendWrapper ? appendWrapper.offsetHeight : 0
|
||||
if (this.showHeader && !headerWrapper) return
|
||||
|
||||
const headerTrElm: HTMLElement = headerWrapper
|
||||
? headerWrapper.querySelector('.el-table__header tr')
|
||||
: null
|
||||
const headerTrElm: HTMLElement = tableHeader ? tableHeader.$el : null
|
||||
const noneHeader = this.headerDisplayNone(headerTrElm)
|
||||
|
||||
const headerHeight = (this.headerHeight.value = !this.showHeader
|
||||
@ -159,7 +161,7 @@ class TableLayout<T> {
|
||||
return nextTick(() => this.updateElsHeight())
|
||||
}
|
||||
const tableHeight = (this.tableHeight.value =
|
||||
this.table.vnode.el.clientHeight)
|
||||
this.table?.vnode.el?.clientHeight)
|
||||
const footerHeight = (this.footerHeight.value = footerWrapper
|
||||
? footerWrapper.offsetHeight
|
||||
: 0)
|
||||
@ -169,8 +171,7 @@ class TableLayout<T> {
|
||||
}
|
||||
this.bodyHeight.value =
|
||||
tableHeight - headerHeight - footerHeight + (footerWrapper ? 1 : 0)
|
||||
this.bodyScrollHeight.value =
|
||||
bodyWrapper.querySelector('.el-table__body')?.scrollHeight!
|
||||
this.bodyScrollHeight.value = tableBody?.$el.scrollHeight!
|
||||
}
|
||||
this.fixedBodyHeight.value = this.scrollX.value
|
||||
? this.bodyHeight.value - this.gutterWidth
|
||||
|
@ -3,28 +3,29 @@
|
||||
ref="tableWrapper"
|
||||
:class="[
|
||||
{
|
||||
'el-table--fit': fit,
|
||||
'el-table--striped': stripe,
|
||||
'el-table--border': border || isGroup,
|
||||
'el-table--hidden': isHidden,
|
||||
'el-table--group': isGroup,
|
||||
'el-table--fluid-height': maxHeight,
|
||||
'el-table--scrollable-x': layout.scrollX.value,
|
||||
'el-table--scrollable-y': layout.scrollY.value,
|
||||
'el-table--enable-row-hover': !store.states.isComplex.value,
|
||||
'el-table--enable-row-transition':
|
||||
[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,
|
||||
},
|
||||
tableSize ? `el-table--${tableSize}` : '',
|
||||
ns.m(tableSize),
|
||||
className,
|
||||
'el-table',
|
||||
ns.b(),
|
||||
]"
|
||||
:style="style"
|
||||
:data-prefix="ns.namespace.value"
|
||||
@mouseleave="handleMouseLeave()"
|
||||
>
|
||||
<div class="el-table__inner-wrapper">
|
||||
<div :class="ns.e('inner-wrapper')">
|
||||
<div ref="hiddenColumns" class="hidden-columns">
|
||||
<slot></slot>
|
||||
</div>
|
||||
@ -32,7 +33,7 @@
|
||||
v-if="showHeader"
|
||||
ref="headerWrapper"
|
||||
v-mousewheel="handleHeaderFooterMousewheel"
|
||||
class="el-table__header-wrapper"
|
||||
:class="ns.e('header-wrapper')"
|
||||
>
|
||||
<table-header
|
||||
ref="tableHeader"
|
||||
@ -43,9 +44,10 @@
|
||||
@set-drag-visible="setDragVisible"
|
||||
/>
|
||||
</div>
|
||||
<div ref="bodyWrapper" :style="bodyHeight" class="el-table__body-wrapper">
|
||||
<div ref="bodyWrapper" :style="bodyHeight" :class="ns.e('body-wrapper')">
|
||||
<el-scrollbar ref="scrollWrapper" :height="height">
|
||||
<table-body
|
||||
ref="tableBody"
|
||||
:context="context"
|
||||
:highlight="highlightCurrentRow"
|
||||
:row-class-name="rowClassName"
|
||||
@ -61,29 +63,29 @@
|
||||
v-if="isEmpty"
|
||||
ref="emptyBlock"
|
||||
:style="emptyBlockStyle"
|
||||
class="el-table__empty-block"
|
||||
:class="ns.e('empty-block')"
|
||||
>
|
||||
<span class="el-table__empty-text">
|
||||
<span :class="ns.e('empty-text')">
|
||||
<slot name="empty">{{ computedEmptyText }}</slot>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
v-if="$slots.append"
|
||||
ref="appendWrapper"
|
||||
class="el-table__append-wrapper"
|
||||
:class="ns.e('append-wrapper')"
|
||||
>
|
||||
<slot name="append"></slot>
|
||||
</div>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
<div v-if="border || isGroup" class="el-table__border-left-patch"></div>
|
||||
<div v-if="border || isGroup" :class="ns.e('border-left-patch')"></div>
|
||||
</div>
|
||||
<div
|
||||
v-if="showSummary"
|
||||
v-show="!isEmpty"
|
||||
ref="footerWrapper"
|
||||
v-mousewheel="handleHeaderFooterMousewheel"
|
||||
class="el-table__footer-wrapper"
|
||||
:class="ns.e('footer-wrapper')"
|
||||
>
|
||||
<table-footer
|
||||
:border="border"
|
||||
@ -97,7 +99,7 @@
|
||||
<div
|
||||
v-show="resizeProxyVisible"
|
||||
ref="resizeProxy"
|
||||
class="el-table__column-resize-proxy"
|
||||
:class="ns.e('column-resize-proxy')"
|
||||
></div>
|
||||
</div>
|
||||
</template>
|
||||
@ -106,7 +108,7 @@
|
||||
import { defineComponent, getCurrentInstance, computed, provide } from 'vue'
|
||||
import debounce from 'lodash/debounce'
|
||||
import { Mousewheel } from '@element-plus/directives'
|
||||
import { useLocale } from '@element-plus/hooks'
|
||||
import { useLocale, useNamespace } from '@element-plus/hooks'
|
||||
import ElScrollbar from '@element-plus/components/scrollbar'
|
||||
import { createStore } from './store/helper'
|
||||
import TableLayout from './table-layout'
|
||||
@ -156,6 +158,7 @@ export default defineComponent({
|
||||
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)
|
||||
@ -223,6 +226,7 @@ export default defineComponent({
|
||||
})
|
||||
|
||||
return {
|
||||
ns,
|
||||
layout,
|
||||
store,
|
||||
handleHeaderFooterMousewheel,
|
||||
|
@ -136,9 +136,12 @@ export const getColumnByCell = function <T>(
|
||||
table: {
|
||||
columns: TableColumnCtx<T>[]
|
||||
},
|
||||
cell: HTMLElement
|
||||
cell: HTMLElement,
|
||||
namespace: string
|
||||
): null | TableColumnCtx<T> {
|
||||
const matches = (cell.className || '').match(/el-table_[^\s]+/gm)
|
||||
const matches = (cell.className || '').match(
|
||||
new RegExp(`${namespace}-table_[^\\s]+`, 'gm')
|
||||
)
|
||||
if (matches) {
|
||||
return getColumnById(table, matches[0])
|
||||
}
|
||||
@ -426,6 +429,7 @@ export const isFixedColumn = <T>(
|
||||
}
|
||||
|
||||
export const getFixedColumnsClass = <T>(
|
||||
namespace: string,
|
||||
index: number,
|
||||
fixed: string | boolean,
|
||||
store: any,
|
||||
@ -435,7 +439,7 @@ export const getFixedColumnsClass = <T>(
|
||||
const { direction, start } = isFixedColumn(index, fixed, store, realColumns)
|
||||
if (direction) {
|
||||
const isLeft = direction === 'left'
|
||||
classes.push(`el-table-fixed-column--${direction}`)
|
||||
classes.push(`${namespace}-fixed-column--${direction}`)
|
||||
if (isLeft && start === store.states.fixedLeafColumnsLength.value - 1) {
|
||||
classes.push('is-last-column')
|
||||
} else if (
|
||||
|
Loading…
Reference in New Issue
Block a user