element-plus
Version:
A Component Library for Vue3.0
164 lines (157 loc) • 4.76 kB
text/typescript
import {
getCurrentInstance,
h,
ComputedRef,
ref,
computed,
watchEffect,
} from 'vue'
import { cellForced, defaultRenderCell, treeCellPrefix } from '../config'
import { parseWidth, parseMinWidth } from '../util'
import { TableColumn, TableColumnCtx } from '../table.type'
function useRender(props: TableColumnCtx, slots, owner: ComputedRef<any>) {
const instance = (getCurrentInstance() as unknown) as TableColumn
const columnId = ref('')
const isSubColumn = ref(false)
const realAlign = ref<string>()
const realHeaderAlign = ref<string>()
watchEffect(() => {
realAlign.value = !!props.align ? 'is-' + props.align : null
// nextline help render
realAlign.value
})
watchEffect(() => {
realHeaderAlign.value = !!props.headerAlign
? 'is-' + props.headerAlign
: realAlign.value
// nextline help render
realHeaderAlign.value
})
const columnOrTableParent = computed(() => {
let parent = (instance.vnode as any).vParent || (instance.parent as any)
while (parent && !parent.tableId && !parent.columnId) {
parent = (parent.vnode as any).vParent || (parent.parent as any)
}
return parent
})
const realWidth = ref(parseWidth(props.width))
const realMinWidth = ref(parseMinWidth(props.minWidth))
const setColumnWidth = column => {
if (realWidth.value) column.width = realWidth.value
if (realMinWidth.value) {
column.minWidth = realMinWidth.value
}
if (!column.minWidth) {
column.minWidth = 80
}
column.realWidth =
column.width === undefined ? column.minWidth : column.width
return column
}
const setColumnForcedProps = column => {
// 对于特定类型的 column,某些属性不允许设置
const type = column.type
const source = cellForced[type] || {}
Object.keys(source).forEach(prop => {
const value = source[prop]
if (value !== undefined) {
column[prop] = prop === 'className' ? `${column[prop]} ${value}` : value
}
})
return column
}
const checkSubColumn = children => {
if (children instanceof Array) {
children.forEach(child => check(child))
} else {
check(children)
}
function check(item) {
if (item?.type?.name === 'ElTableColumn') {
item.vParent = instance
}
}
}
const setColumnRenders = column => {
// renderHeader 属性不推荐使用。
if (props.renderHeader) {
console.warn(
'[Element Warn][TableColumn]Comparing to render-header, scoped-slot header is easier to use. We recommend users to use scoped-slot header.',
)
} else if (column.type !== 'selection') {
column.renderHeader = scope => {
// help render
instance.columnConfig.value['label']
const renderHeader = slots.header
return renderHeader ? renderHeader(scope) : column.label
}
}
let originRenderCell = column.renderCell
// TODO: 这里的实现调整
if (column.type === 'expand') {
// 对于展开行,renderCell 不允许配置的。在上一步中已经设置过,这里需要简单封装一下。
column.renderCell = data =>
h(
'div',
{
class: 'cell',
},
[originRenderCell(data)],
)
owner.value.renderExpanded = data => {
return slots.default ? slots.default(data) : slots.default
}
} else {
originRenderCell = originRenderCell || defaultRenderCell
// 对 renderCell 进行包装
column.renderCell = data => {
let children = null
if (slots.default) {
children = slots.default(data)
} else {
children = originRenderCell(data)
}
const prefix = treeCellPrefix(data)
const props = {
class: 'cell',
style: {},
}
if (column.showOverflowTooltip) {
props.class += ' el-tooltip'
props.style = {
width: (data.column.realWidth || data.column.width) - 1 + 'px',
}
}
checkSubColumn(children)
return h('div', props, [prefix, children])
}
}
return column
}
const getPropsData = (...propsKey: unknown[]) => {
return propsKey.reduce((prev, cur) => {
if (Array.isArray(cur)) {
cur.forEach(key => {
prev[key] = props[key]
})
}
return prev
}, {})
}
const getColumnElIndex = (children, child) => {
return [].indexOf.call(children, child)
}
return {
columnId,
realAlign,
isSubColumn,
realHeaderAlign,
columnOrTableParent,
setColumnWidth,
setColumnForcedProps,
setColumnRenders,
getPropsData,
getColumnElIndex,
}
}
export default useRender