我有一个项目需要以下内容。
将在代码中声明四个数组:
var ROW1 = ['module1'];
var ROW2 = ['module2', 'module3'];
var ROW3 = ['module4', 'module5', 'module6'];
var ROW4 = ['module7', 'module8'];
这些数组的每个元素代表可配置HTML小部件中的模块。根据每个数组中指定的元素,代码将构建一个代表这些“模块”的HTML - 每个“ROWx”数组将是一个表行(),每个模块将是表格中的表格单元格。
ROW1可以为空(在这种情况下它不会包含在HTML中)或者有一个模块“module1”。
ROW2,ROW3和ROW4每个都有0到3个模块(任何模块2 - 模块8,任何顺序)。
使用上面的示例数组,我将以编程方式生成这样的HTML表:
<table>
<tr id="row1">
<td colspan="6">[module1]</td>
</tr>
<tr id="row2">
<td colspan="3">[module2]</td>
<td colspan="3">[module3]</td>
</tr>
<tr id="row3">
<td colspan="2">[module4]</td>
<td colspan="2">[module5]</td>
<td colspan="2">[module6]</td>
</tr>
<tr id="row4">
<td colspan="3">[module7]</td>
<td colspan="3">[module8]</td>
</tr>
</table>
(colspans就是为了保持正确的表格布局; 6是1,2和3之间的最低公倍数。)
问题是,这些模块的内容是动态填充的(我从AJAX调用到返回JSON对象的URL),并且内容并不总是可用于每个模块。我没有为没有内容的模块创建一个空单元格(),而是希望从布局中完全删除该单元格,就像从未在原始配置中那样(即顶部的数组)。
我已经花了很多时间创建抽象模块创建的代码 - 它根据每行中有多少个模块创建一个“shell”HTML布局,然后将内容附加到相应的表格单元格中模块应该在那里。我希望能够继续使用该代码,所以我认为最好的方法是在构建“shell”之前遍历数组中的每个元素,如果我没有内容,则删除该元素从阵列。然后我可以使用新修改的数组按照惯例构建“shell” - 我基本上只是事先处理它来检查每个模块中的内容,如果没有可用的话,就像那个模块一样从未在初始数组中设置(通过在新数组中删除它然后使用它来构建“shell”)。
例如,假设配置如下:
var ROW1 = ['module1'];
var ROW2 = ['module4', 'module2'];
var ROW3 = ['module5'];
var ROW4 = ['module7', 'module3', 'module8'];
我想浏览每个数组中的每个元素,并检查模块中的可用内容。假设“module3”和“module5”没有可用的内容。我想最终得到这些数组:
var ROW1 = ['module1'];
var ROW2 = ['module4', 'module2'];
var ROW3 = ['module7', 'module8'];
请注意行发生了什么 - 因为“module5”被删除,ROW4数组中的元素被转移到ROW3,然后删除了ROW4。此外,在新的ROW3(以前的ROW4)中,删除了“module3”,将“module8”从位置[2]滑动到位置[1]。
所以:
BEFORE(根据配置要求):
<table>
<tr id="row1">
<td colspan="6">[module1]</td>
</tr>
<tr id="row2">
<td colspan="3">[module4]</td>
<td colspan="3">[module2]</td>
</tr>
<tr id="row3">
<td colspan="6">[module5]</td>
</tr>
<tr id="row4">
<td colspan="2">[module7]</td>
<td colspan="2">[module3]</td>
<td colspan="2">[module8]</td>
</tr>
</table>
AFTER(基于实际可用的内容)
<table>
<tr id="row1">
<td colspan="6">[module1]</td>
</tr>
<tr id="row2">
<td colspan="3">[module4]</td>
<td colspan="3">[module2]</td>
</tr>
<tr id="row3">
<td colspan="3">[module7]</td>
<td colspan="3">[module8]</td>
</tr>
</table>
回想一下ROW1是一种特殊情况,因为它不会影响其他行。如果内容可用于“module1”(唯一可以进入ROW1的模块),那么ROW1应该保持不变。如果没有可用的内容,则可以删除ROW1,但仍然保留ROW2,ROW3和ROW4(即不将它们各自向上移动一行)。我真的只需要一个处理ROW2,ROW3和ROW4的解决方案,因为ROW1的逻辑非常简单。
我是初学者/中级JavaScript程序员,对数组没有太多经验。我一直在打开和关闭这几个小时,但只是不觉得我想出的是一个强大或优雅/紧凑的方法。
如果任何JavaScript大师可以共享此解决方案,我会非常感激!非常感谢。
答案 0 :(得分:4)
首先,将行存储在一个数组中,你的ROW1-ROW4会让你头疼。
var ROWS = [
['module1'],
['module4', 'module2'],
['module5'],
['module7', 'module3', 'module8']
];
您还想要一种删除元素的方法。 .splice()
内置于数组中,可以很好地删除元素。
// lets clear out our disabled modules
var disabledModules = ['module3', 'module5'];
// quick sample function - yours might check for empty content or whatever else...
function isDisabled(module) {
for (var i=0, test; test=disabledModules[i]; i++) {
if (test === module) return true;
}
return false;
}
for(var i=0,row; row=ROWS[i]; i++) {
for (var j=0,module; module=row[j]; j++) {
// is this module in our disabled modules list?
if (isDisabled(module)) { // the module is disabled
row.splice(j,1);
j--; // so we recheck this point in the array
}
}
if (row.length < 1) {
// all items were deleted
ROWS.splice(i,1);
i--; // so we recheck this point..
}
}
// ROWS === [["module1"], ["module4", "module2"], ["module7", "module8"]]
您的评论询问了所使用的for循环语法。这是一种非常快速的方法来循环遍历您不知道“假”值的数组。分开一个并打开详细记录:
for(
// Part 1 of for loop: Setup, create two variables, i=0, and row.
var i=0,row;
// Part 2: The test - when false, loop will exit, gets executed pre-loop every time
// Assignment operator returns the value assigned, so row=ROWS[i] will be undefined
// (false) when we reach then end of the array.
row=ROWS[i];
// Part 3: Post loop - increment i
i++) {
使用此方法的危险确实存在,例如,如果它是一个数字数组,并且其中一个数字为0,则循环将提前退出。另一种方法是写:
for(var i=0; i<ROWS.length; i++) {
var row = ROWS[i];
}