我正在尝试递归循环对象并在HTML中以有组织的方式输出数据。下面是我到目前为止,但我目前卡住了,因为我只能输出行而不是缩进级别。 preview
元素中的样本数据是我正在尝试做的输出表示。
此外,如果有更好的方式来组织/构建数据(通过分组或类似),我将不胜感激。
var obj = {
0: {
"Shirts": 0,
"Jeans": 1,
"Brand": "Lorem ipsum"
},
1: {
"Color": {
"blue" : 1,
"red" : 0
},
"Size": {
"Man": {
"small": 1,
"medium": 0,
"large": 0
},
"Women": {
"small": 1,
"medium": 1,
"large": 1
}
}
},
2: {
"Shipping": {
"overNight": "$ 10",
"3 days": "$ 4"
}
},
3: {
"Stock": {
"Man": [
{
"green jeans": 13,
"green shirts": 17,
"green shoes": 21
},
{
"black jeans": 1,
"black shirts": 12,
"black shoes": 53
}
],
"Women": [
{
"green jeans": 2,
"green shirts": 53,
"green shoes": 11
},
{
"black jeans": 6,
"black shirts": 22,
"black shoes": 29
}
]
}
}
}
var dataEl = document.getElementById('data');
var getProperties = function (obj) {
for (var property in obj) {
if (!obj.hasOwnProperty(property)) continue;
if (obj.hasOwnProperty(property) && obj[property] !== null) {
if (obj[property].constructor == Object) {
dataEl.innerHTML += '<div class="row title">' + property + '</div>';
getProperties(obj[property])
} else if (obj[property].constructor == Array) {
dataEl.innerHTML += '<div class="row title">' + property + '</div>';
for (var i = 0; i < obj[property].length; i++) {
getProperties(obj[property][i]);
}
} else {
dataEl.innerHTML += '<div class="row"><span>' + property +'</span>: ' + obj[property] + '</div>';
}
}
}
}
//getProperties(obj);
#data,
#preview {
display: block;
width: 80%;
font-size: 12px;
font-family: Arial, Helvetica;
padding: 10px;
}
#data .row,
#preview .row {
display: inline-block;
width: 100%;
margin-bottom: 2px;
}
#data .row.title,
#preview .row.title {
font-weight: bold;
font-size: 14px;
}
#data .row.indent-1,
#preview .row.indent-1 {
padding-left: 20px;
}
#data .row.indent-2,
#preview .row.indent-2 {
padding-left: 40px;
}
<div id="data"></div>
<!-- This is how it should be structured -->
<div id="preview">
<div class="row"><span>Shirts:</span>0</div>
<div class="row"><span>Jeans:</span>1</div>
<div class="row"><span>Brand:</span>Lorem ipsum</div>
<div class="row title">Color</div>
<div class="row indent-1"><span>blue:</span> 1</div>
<div class="row indent-1"><span>red:</span> 0</div>
<div class="row title">Size</div>
<div class="row title indent-1">Man</div>
<div class="row indent-2"><span>small:</span> 1</div>
<div class="row indent-2"><span>medium:</span> 0</div>
<div class="row indent-2"><span>large:</span> 0</div>
<div class="row title indent-1">Women</div>
<div class="row indent-2"><span>small:</span> 1</div>
<div class="row indent-2"><span>medium:</span> 1</div>
<div class="row indent-2"><span>large:</span> 1</div>
<div class="row title">Shipping</div>
<div class="row indent-1"><span>overNight:</span> $ 10</div>
<div class="row indent-1"><span>3 days:</span> $ 4</div>
<div class="row title">Stock</div>
<div class="row title indent-1">Man</div>
<div class="row indent-2"><span>green jeans:</span> 13</div>
<div class="row indent-2"><span>green shirts:</span> 17</div>
<div class="row indent-2"><span>green shoes:</span> 21</div>
<div class="row indent-2"><span>black jeans:</span> 1</div>
<div class="row indent-2"><span>black shirts:</span> 127</div>
<div class="row indent-2"><span>black shoes:</span> 53</div>
<div class="row title indent-1">Women</div>
<div class="row indent-2"><span>green jeans:</span> 2</div>
<div class="row indent-2"><span>green shirts:</span> 53</div>
<div class="row indent-2"><span>green shoes:</span> 11</div>
<div class="row indent-2"><span>black jeans:</span> 6</div>
<div class="row indent-2"><span>black shirts:</span> 22</div>
<div class="row indent-2"><span>black shoes:</span> 29</div>
</div>
答案 0 :(得分:2)
当您使用html构造的递归函数时,不是将结果字符串直接附加到元素中,而是将其存储到变量&amp;在函数完成后返回它,这使得将结果更容易封装在分组元素中 - 请参阅与源对象兼容的示例方法:
function getProperties(obj, depth) {
depth = depth === undefined ? 0 : depth + 1;
var html = '';
// first handle arrays
if (obj && obj.forEach) {
html += '<div class="list" data-indent="' + depth + '">';
obj.forEach(function (elems, index) {
html += '<div class="item ' + (index % 2 ? 'even' : 'odd') + '" data-index"' + index + '">'
+ getProperties(elems, depth)
+ '</div>';
});
html += '</div>';
}
// the main block (comes after arrays as an array would pass this condition too)
else if (obj && typeof obj === 'object') {
// uncomment if you'd like the whole group enclosed in a parent:
// if (depth === 0) html += '<div class="group">';
Object.keys(obj).forEach(function (key) {
html += '<div class="row" data-indent="' + depth + '">';
if (depth > 0)
html += '<span class="title">' + key + '</span>'
html += getProperties(obj[key], depth)
html += '</div>';
});
// if (depth === 0) html += '</div>';
}
// else the object is just a value
else {
html += '<span class="value">' + obj + '</span>';
}
return html;
}
document.getElementById('data').innerHTML = getProperties(obj);
您可以看到内部迭代(forEach
调用)我只是将另一个getProperties
调用的结果附加到结果字符串(html
变量)。
另一个优点是你不会搞&&#34;全球状态&#34; (#data元素的innerHTML),因此无论元素的内容是什么,函数总是返回相同的结果 - 这就是所谓的函数方法。
如上所述,嵌套元素包含在父元素中,这使得缩进更容易 - 只需在父元素上设置margin-left(参见下面的CSS)。
我用迭代函数(forEach
)替换for循环以获得更多功能样式,并且在数组的情况下防止引入中间变量(i
),但它只是一个问题偏好;使用特征检测时,条件也有点不同(对象是否具有我将要使用的功能,例如forEach
?)Object.keys
可以使用在object
类型的任何对象上(这是为什么数组resp。forEach
检测之前出现,数组也是object
类型)并且不建议检查构造函数因为它可以被自定义覆盖。
我还添加了depth
(data-indent
属性的内容,这里没有任何意义,但你可能会以某种方式使用它)&amp;由数组迭代产生的组的奇数/偶数类,我认为这些都是不言自明的。
我改变了css类,试图让它更具上下文意义,使用这个css应该说清楚:
.row {
margin-left: 10px;
}
.title {
font-weight: bold;
}
.value {
padding-left: 10px;
}
.list .odd {
background-color: lightgray;
}
/* just to see how to target a custom attribute */
[data-indent="3"] {
color: red;
}
(需要自定义属性的data-
前缀才能使其符合HTML验证程序。)