我的輸入是
{
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)