cjd-parkball
Version:
> 中后台业务组件库,中后台就像公园,进入需要买门票(登录),所以以 Parkball(公园球) 命名,公园内必定捕获!作为一个组件库,提供使用方法文档,方便开发者的调用
156 lines (149 loc) • 5.64 kB
JavaScript
// 检查render属性,作用是检查columns配置中是否含有render属性并进一步检查render是否
const haveProps = (items, proto) => {
// 如果都没有render属性
const noneHasRender = items.every(item => !item.render)
if (noneHasRender) return []
// 有render属性,那么其必定是个函数,运行每个函数,暂存每个结果并加以判断
const renderRes = items.map((item) => {
if (typeof item.render === 'function') return item.render()
return item
})
// 检查每个render的函数结果是否含有props属性且props属性是否含有rowSpan以及colSpan
// 每个render函数返回的都是ReactElement对象
const allOfThemAreReactElement = renderRes.every(item => item.$$typeof && item.$$typeof.toString() === 'Symbol(react.element)')
if (allOfThemAreReactElement) return []
// 是否存在props属性
const defective = []
const noneHasProps = renderRes.every(item => !item.props)
if (noneHasProps) return []
renderRes.forEach((item, index) => {
// 判断object中是否存在proto
// toString防止存在rowSpan或者colSpan为0的情况无法得到合并的dataIndex
if (item.props && (typeof item.props[proto] === 'number')) {
const dataIndex = items[index].key || items[index].dataIndex
defective.push(dataIndex)
}
})
if (defective.length === 0) return []
return defective
}
// 输出两个数组之间的不同的值
/* eslint-disable */
const difference = (source, target) => {
if (target.length === 0) return source
let index = -1
const res = []
const targetLength = target.length
outer:
while (++index < source.length) {
const value = source[index]
let targetIndex = targetLength
while (targetIndex --) {
if (target[targetIndex] === value) continue outer
res.push(value)
}
}
return res
}
// 数组形式的collapseRow
const getRowSpanDataByArray = (shouldRerender, dataSource) => {
// 如果传入的配置单纯是数组的话,那么简单的按照传入的dataIndex来合并行
const rowSpanData = {}
// 计数有几个相同的
let count = 1
let tempVal = undefined
let index = -1
const dataIndexLength = shouldRerender.length
/**
* 得到如下的结构的数据
* {
* key: {
* start: 记录开始的index信息
* length: 同一个dataIndex的相同值的长度
* }
* }
*/
while(++ index < dataIndexLength) {
const _dataIndex = shouldRerender[index]
let start = 0
dataSource.forEach((item, index) => {
const current = item[_dataIndex]
if (current !== tempVal) {
if (!rowSpanData[current]) rowSpanData[current] = []
if (tempVal) rowSpanData[tempVal].push({
start,
length: count
})
start = index
tempVal = current
count = 1
return 0
}
count ++
})
// 补全最后一个的长度信息
rowSpanData[tempVal].push({
start,
length: count
})
}
return rowSpanData
}
function formatColumns (sourceColumns) {
const { collapseRow, collapseCol, dataSource } = this.props
// 如果不存在collapseRow或者collapseCol属性返回原始的sourceColumns配置
if (!(collapseRow || collapseCol)) return sourceColumns
// console.log('[source columns]', sourceColumns)
/**
* collapseRow, collapseCol
* 当参数是array类型的时候,单纯判断dataIndex的value是否相等
* 根据dataIndex的value值来确定是否合并
* hint: 如果该dataIndex存在render且返回值并非是React.Element的情况
* 则判断使用者使用自己规定的渲染逻辑,则放弃重写渲染函数
*/
if (collapseRow && Array.isArray(collapseRow)) {
// 如果存在合并行的配置信息
// 判断该dataIndex是否存在render函数且render函数包含合并的处理信息
const collapseRowItems = []
collapseRow.forEach((item) => {
const _tar = sourceColumns.find((i) => {
const colName = i.key || i.dataIndex
return colName === item
})
if (_tar) collapseRowItems.push(_tar)
})
// 检查render中是否存在合并的配置
const dataIndexExclude = haveProps(collapseRowItems, 'rowSpan')
// 如果返回值都是false那么意味用户传入的数组的每个dataIndex都需要写入render
// 如果返回是一个数组,则数组内的dataIndex的render函数则不能重写
const shouldRerender = difference(collapseRow, dataIndexExclude)
const rowSpanData = getRowSpanDataByArray(shouldRerender, dataSource)
const processedColumns = sourceColumns.map((item) => {
const colName = item.key || item.dataIndex
const tarIndex = shouldRerender.findIndex(i => i === colName)
if (tarIndex >= 0) {
// 重写render函数
const ORIGINALRENDER = item.render
item.render = (text, row, index) => {
const dataCollections = rowSpanData[text]
const currentSet = dataCollections.filter(i => i.start === index)
const rowSpan = currentSet.length > 0 ? currentSet[0].length : 0
return {
children: ORIGINALRENDER ? ORIGINALRENDER.call(this, text, row, index) : text,
props: {
rowSpan,
},
}
}
}
return item
})
return processedColumns
} else {
// 错误提示
console.error('[warning]value of collapseRow got undefined or wrong type, which except an array-type')
console.error('[unexcept output]we will ignore the props of "collapseRow" in this instance')
}
return sourceColumns
}
export default formatColumns