vue-virtualized-table-booway
Version:
The second version of implementation of `vue-virtual-table` component, it was inspired from [rc-table](https://github.com/react-component/table) and [ant-table](https://ant.design/components/table), API design is 60%+ consistent. Or you could think I tran
223 lines (201 loc) • 6.62 kB
JSX
/* eslint-disable vue/require-default-prop */
import {
noop,
isObject,
isNumber,
isFunction,
isValidArray
} from '../utils/type'
import TableCell from '../TableCell/index'
import {renderExpandIcon} from '../utils/expand'
import {TableProps, ARRAY_PROP, OBJECT_PROP} from '../interface'
function getSpan(row, index, span) {
if (isFunction(span)) {
span = span(row, index)
}
if (isNumber(span)) {
return span
}
return 1
}
export default {
name: 'BodyRow',
// functional: true,
inheritAttrs: false,
inject: {
store: OBJECT_PROP,
prefixCls: TableProps.prefixCls,
expandable: OBJECT_PROP,
rowSelection: OBJECT_PROP,
rowClassName: TableProps.rowClassName
// isSelectionMode: Boolean,
// isExpansionMode: Boolean,
},
props: {
index: Number,
rowKey: [String, Number],
record: Object,
columnsKey: ARRAY_PROP,
recordKey: [String, Number],
expandedKeys: Array,
rowComponent: String,
cellComponent: String,
fixedInfoList: ARRAY_PROP,
flattenColumns: TableProps.columns,
childrenColumnName: String
},
render(h /* { props, injections } */) {
const {
record,
index,
rowKey,
columnsKey,
expandedKeys,
rowComponent: RowComponent,
cellComponent,
fixedInfoList,
flattenColumns,
childrenColumnName
} = this.$props
const {store, prefixCls, expandable, rowClassName, rowSelection} = this // .injections
const hasNestChildren =
childrenColumnName && record && isValidArray(record[childrenColumnName])
let expanded = false
let onExpand = noop
let indent = 0
if (isObject(expandable)) {
indent = record.__depth || 0
expanded = expandedKeys.includes(rowKey)
onExpand = (record, event) => {
store.toggleRowExpansion(record, undefined, event)
}
}
let selected = null
let onClick = noop
if (rowSelection) {
selected = store.isRowSelected(rowKey)
onClick = (event) => store.toggleRowSelection(record, event)
}
let computeRowClassName
if (typeof rowClassName === 'string') {
computeRowClassName = rowClassName
} else if (typeof rowClassName === 'function') {
computeRowClassName = rowClassName(record, index, indent)
}
let linkClass = []
// if (index === 0 && rowsLength > 1) {
// linkClass.push('linkLine_first');
// }
// if (index === 0 && rowsLength === 1) {
// linkClass.push('linkLine_half_top');
// }
// if (index === rowsLength - 1 && index !== 0) {
// linkClass.push('linkLine_last');
// }
// if (index !== 0) {
// if (record.children && record.children.length > 0) {
// linkClass.push('second_layer');
// } else {
// linkClass.push('third_layer');
// }
// }
const rowsLength = record.__parent ? record.__parent.children.length : 0;
let spanList = [];
let length = record.children ? record.children.length : 0;
if (indent === 0) {
if (length > 0) {
spanList.push(<span class={['shuxian-half-down']}
style={{left: `${(expandable.indentSize || 15) * (indent + 1) + 4.5}px`}}></span>)
}
} else {
if (length > 0) {
spanList.push(<span class={['hengxian']}
style={{left: `${(expandable.indentSize || 15) * indent + 4.5}px`}}></span>)
} else {
spanList.push(<span class={['hengxian']}
style={{left: `${(expandable.indentSize || 15) * (indent + 1) + 4.5 - 17}px`, width: '33px'}}></span>)
}
for (let i = 0; i < indent + 1; i++) {
if (i === indent) {
if(length > 0) {
spanList.push(<span class={['shuxian-half-down']}
style={{left: `${(expandable.indentSize || 15) * (indent + 1) + 4.5}px`}}></span>)
}
} else {
if (i === indent - 1 && record.__index === rowsLength - 1) {
spanList.push(<span class={['shuxian-half-up']}
style={{left: `${(expandable.indentSize || 15) * indent + 4.5}px`, height: '50%'}}></span>)
} else {
spanList.push(<span class={['shuxian-all']}
style={{left: `${(expandable.indentSize || 15) * (i + 1) + 4.5}px`}}></span>)
}
}
}
}
return (
<RowComponent
data-row-key={rowKey}
class={[
`${prefixCls}-row`,
`${prefixCls}-row-level-${indent}`,
selected && `${prefixCls}-row-selected`,
computeRowClassName
]}
onClick={onClick}
>
{flattenColumns.map((column, colIndex) => {
const {prop, className: columnClassName} = column
const key = (columnsKey || [])[colIndex]
const fixedInfo = fixedInfoList[colIndex]
// ============= Used for nest expandable =============
let appendCellNode
if (
column.expandable &&
isObject(expandable) &&
isFunction(onExpand)
) {
appendCellNode = [
...spanList,
<span
style={{
paddingLeft: `${(expandable.indentSize || 15) * indent}px`
}}
class={[`${prefixCls}-row-indent indent-level-${indent}`, ...linkClass]}
/>,
(isFunction(expandable.expandIcon)
? expandable.expandIcon
: renderExpandIcon)(h, {
prefixCls,
expanded,
expandable: isFunction(expandable.rowExpandable)
? expandable.rowExpandable(record, index, rowKey)
: record.hasChildren || hasNestChildren,
record,
onExpand
})
]
}
return (
<TableCell
key={key}
class={columnClassName}
index={index}
record={record}
prop={prop}
colSpan={getSpan(record, index, column.colSpan)}
rowSpan={getSpan(record, index, column.rowSpan)}
column={column}
ellipsis={column.ellipsis}
align={column.align}
component={cellComponent}
prefixCls={prefixCls}
shouldCellUpdate={column.shouldCellUpdate}
appendNode={appendCellNode}
{...{props: fixedInfo}}
/>
)
})}
</RowComponent>
)
}
}