我的输入是
{
A1: {
B1: {
C1: {
D1: 1233,
D2: 11
},
C2: {
D1: 10,
D2: 10
}
},
B2: {
C1: {
D1: 10,
D2: 11
},
C2: {
D1: 10,
D2: 10
},
C3: {
D1: 10,
D2: 10
}
}
}
}
用什么框架都可以,只要求输出以下table, json的最后一个节点就是table的最后一个column,并且只能占据一行,也就是rowspan要为1.然后难点在于怎么判断前面的column占用的rowspan,我一点思路的都没有囧…
更新:
如果有代码演示最好了,底下评论的朋友谢谢了,我看了文章还是想不出来改怎么写代码…
回答:
树的递归,根据后代叶子节点数量决定当前节点所跨的行,深度优先适合此场景。
代码实现:http://jsrun.net/AXaKp/edit
function getRows (data) {
const result = []
const values = Object.values(data)
if (values.some(v => typeof v !== 'object' || !v || !Object.keys(v).length)) {
result.push([{
text: Object.keys(data).join(', '),
rowspan: 1
}])
return result
}
for (let k in data) {
const pathList = getRows(data[k])
if (pathList.length) {
const first = pathList[0]
first.unshift({
text: k,
rowspan: pathList.length
})
}
result.push(...pathList)
}
return result
}
function generateHtml (rows, head) {
return `
${ head.map(h => `
${h}`).join('') }${rows.map(r => {
return `
${r.map(({ text, rowspan }) => `
${text}`).join('')}`
}).join('\n')}
`
}
function render (data) {
const rows = getRows(data)
const head = (rows[0] || []).map(r => `Column-${r.text[0]}`)
const html = generateHtml(rows, head)
const div = document.createElement('div')
div.innerHTML = html
document.body.appendChild(div)
}
测试:
render(data)
效果:
回答:
这是一个树形结构,遍历这棵树,通过递归把每个节占据的行数算出来(就是每个子节点占据的行数之后)。然后你在渲染表格的时候就知道 rowspan 该是多少了(注意:如果为 1 可以省略哦)
给个提示
function calcRows(node) {
const keys = Object.keys(node);
const rowspan = node.rowspan = keys.reduce((sum, key) => sum + calcRows(node[key]), 0);
return rowspan;
}
回答:
把JSON对象视为树,表格的单元格就是节点,每一行就是节点的路径。这样每个单元格的rowSpan就是其路径的数量。
const data = {
A1: {
B1: {
C1: {
D1: 1233,
D2: 11
},
C2: {
D1: 10,
D2: 10
}
},
B2: {
C1: {
D1: 10,
D2: 11
},
C2: {
D1: 10,
D2: 10
},
C3: {
D1: 10,
D2: 10
}
}
}
}
// 利用递归方式的深度优先遍历算法计算每个节点的路径数量,并保持路径列表
function getPath(node, key) {
const pathList = Object.keys(node).reduce((pathList, key) => {
return pathList.concat(getPath(node[key], key));
}, [])
const pathCount = pathList.length;
pathList.map((path, index) => {
// 这里特殊处理下:只在第一条路径里插入当前节点key,其他路径不插入,方便生成`tr`
path.unshift(!!index ? null : { key, pathCount })
return path;
});
return pathList.length ? pathList : [[{ key, pathCount: 1 }]]
}
// 路径列表转成`tr`列表
function toTableRows(data) {
const pathList = getPath(data, 'root');
const rows = pathList.map((row, index) => {
const tr = ['
'];for(let i = 1; i < row.length; ++i) {
if(row[i]) {
const { key, pathCount } = row[i];
tr.push(`
${key}`)}
}
return tr.join('')
})
return rows.join('')
}
document.getElementById('table').innerHTML = toTableRows(data)