【问题标题】:Dynamically append multiple TRs动态追加多个 TR
【发布时间】:2017-02-09 10:21:54
【问题描述】:

我有以下数组:

arr = [{
  "ID": 1,
  "animals": {
    "dog": {
      "color": "brown",
      "age": 5
    },
    "cat": {
      "color": "white",
      "age": 3
    }
  }
}, {
  "ID": 2,
  "animals": {
    "cat": {
      "color": "black",
      "age": 7
    }
  }
}, {
  "ID": 3,
  "animals": {
    "mouse": {
      "color": "white",
      "age": 1
    },
    "dog": {
      "color": "black",
      "age": 9
    },
    "cat": {
      "color": "grey",
      "age": 4
    }
  }
}]

我需要制作这张桌子:

或者作为代码:

<table border="1" id="myTab">
  <tr>
    <td>ID</td>
    <td>Animal</td>
    <td>Color</td>
    <td>Age</td>
  </tr>
  <tr>
    <td rowspan="2">1</td>
    <td>cat</td>
    <td>3</td>
    <td>white</td>
  </tr>
  <tr>
    <td>dog</td>
    <td>5</td>
    <td>brown</td>
  </tr>
  <tr>
    <td rowspan="1">2</td>
    <td>cat</td>
    <td>7</td>
    <td>black</td>
  </tr>
  <tr>
    <td rowspan="3">3</td>
    <td>mouse</td>
    <td>1</td>
    <td>white</td>
  </tr>
  <tr>
    <td>dog</td>
    <td>9</td>
    <td>black</td>
  </tr>
  <tr>
    <td>cat</td>
    <td>4</td>
    <td>grey</td>
  </tr>
</table>

Here我学会了合并多个tr的正确方法。

但是,在我的示例中它仍然不起作用:

$.each(arr, function(key, value) {
  var rowspan = Object.keys(arr[key].animals).length;

  var tr = "";
  c = 0;
  $.each(value, function(key2, value2) {
    if (key2 != "animals") {
      if (rowspan < 1) {
        rowspan = 1;
      }
      tr += '<td rowspan=' + rowspan + '>' + value2 + '</td>';
    } else {
      $.each(value2, function(key3, value3) {
        var tr2_temp = "";

        tr2_temp += "<td>" + key3 + "</td>";
        $.each(value3, function(key4, value4) {
          tr2_temp += "<td>" + value4 + "</td>";
        });

        if (c == 0) {
          $('#myTab tr:eq(' + parseInt(key + 1) + ')').append(tr2_temp)
          c++;
        } else {
          $('#myTab tr:eq(' + parseInt(key + 1) + ')').after(tr2_temp)
          c = 0;
        }
      });
    }
  });
  $('#myTab > tbody:last-child').append('<tr>' + tr + '</tr>');
});

Here is a fiddle.

【问题讨论】:

  • 如果你要硬编码你的表标记,基于数组,你想看到什么样的表结构作为输出?仅基于代码,您似乎做出了一些合乎逻辑的选择,因此查看您期望的实际输出会很有帮助。
  • @Fran:我添加了所需表格的代码。

标签: javascript jquery arrays json html-table


【解决方案1】:

虽然我建议您不要将动物类型用作属性名称,因为如果您有多个相同类型的动物而是使用属性可能会导致问题,命名为 type,其值为dog, cat, etc..,使用你现有的条件,你可以像下面那样做。

另外,我建议你先写入内存中的一个变量,然后对 DOM 进行一次追加。

arr = [{
    "ID": 1,
    "animals": {
        "dog": {
            "color": "brown",
            "age": 5
        },
        "cat": {
            "color": "white",
            "age": 3
        }
    }
}, {
    "ID": 2,
    "animals": {
        "cat": {
            "color": "black",
            "age": 7
        }
    }
}, {
    "ID": 3,
    "animals": {
        "mouse": {
            "color": "white",
            "age": 1
        },
        "dog": {
            "color": "black",
            "age": 9
        },
        "cat": {
            "color": "grey",
            "age": 4
        }
    }
}]

var rowspanTemplate = '<tr><td rowspan="{0}">{1}</td><td>{2}</td><td>{3}</td><td>{4}</td></tr>'
var simpleTemplate = '<tr><td>{0}</td><td>{1}</td><td>{2}</td></tr>'
var $newRows = $('<div></div>');

$.each(arr, function(key, value) {
    var newRow;
    var animalTypes = Object.keys(value.animals);
    var i;
    var animalType;

    for (i = 0; i < animalTypes.length; i++) {
        animalType = animalTypes[i];

        if (i === 0) {
            newRow = rowspanTemplate
                .replace('{0}', animalTypes.length)
                .replace('{1}', value.ID)
                .replace('{2}', animalType)
                .replace('{3}', value.animals[animalType].color)
                .replace('{4}', value.animals[animalType].age)
        } else {
            newRow = simpleTemplate
                .replace('{0}', animalTypes[i])
                .replace('{1}', value.animals[animalType].color)
                .replace('{2}', value.animals[animalType].age)
        }

        $newRows.append($(newRow));
    }
})

$('#myTab').append($newRows.html());
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table border="1" id="myTab">
  <tr>
    <td>ID</td>
    <td>Animal</td>
    <td>Color</td>
    <td>Age</td>
  </tr>
</table>

【讨论】:

  • 在我的真实案例中,有 >20 个不同的列。有什么方法可以让它更加动态,而不是替换每一个?
  • @user1170330 您可以使用 angular、knockout 或类似方法为您完成此操作,但对于像这样的简单映射,我不会引入这样的严重依赖,除非您已经在使用它们 :)即使有 100 列,您只需要编写映射器的列,就是这样。使它成为一个函数,传入数组的一部分,它返回带有映射值的tr。这样,您还可以独立地针对映射器编写单元测试。您还可以编写 string.format 扩展,传递参数数组,将 {x} 动态替换为相同位置的值。
【解决方案2】:
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script>
arr = [{
  "ID": 1,
  "animals": {
    "dog": {
      "color": "brown",
      "age": 5
    },
    "cat": {
      "color": "white",
      "age": 3
    }
  }
}, {
  "ID": 2,
  "animals": {
    "cat": {
      "color": "black",
      "age": 7
    }
  }
}, {
  "ID": 3,
  "animals": {
    "mouse": {
      "color": "white",
      "age": 1
    },
    "dog": {
      "color": "black",
      "age": 9
    },
    "cat": {
      "color": "grey",
      "age": 4
    }
  }
}]

function getAttr(obj) {
 var props;
 for (var prop in obj) {
    props += '<td>'+obj[prop]+'</td>';
  }
  return props;
}

function extractChildren(animal,obj) {
    return '<td>'+animal+'</td>' + getAttr(obj) + '';
}
function addRows() {
  for(var i=0; i<arr.length; i++) {
    var children = [];
    var rows = 0;

    for (var prop in arr[i].animals) {
      rows++;
      children.push(extractChildren(prop,arr[i].animals[prop]));
    }
    $('#tbl tbody').append(
    `<tr>
        <td rowspan="`+rows+`">`+ arr[i].ID+ `</td>`+children[0]+`
    </tr>`
    );
    children.shift();
    for(var j=0; j<children.length; j++) {
        $('#tbl tbody').append(`<tr>`+children[j]+`</tr>`);
    }
    }
}
$( document ).ready(function() {
    addRows();
});
</script>
<table id="tbl" border="1">
  <thead>
    <th>ID</th>
    <th>Animal</th>
    <th>Colour</th>
    <th>Age</th>
  </thead>
  <tbody>
  </tbody>

【讨论】:

  • thead ,tfoottbody 是可选的,并且在循环内将元素附加到 DOM 以及执行 .find 是最低效的方法,并且可能会减慢处理的行数少于 100 的页面的呈现。
  • 它们是可选的,但完全有效,操作人员询问动态添加 TR,那么我们如何避免将元素附加到 DOM?您的答案还使用带有附加的循环。但是不需要正确的发现我已经调整了答案
  • 我不会在循环中附加到 DOM,因为那样会非常糟糕。我附加到内存中,并且仅在我完成附加到 DOM 1 次之后。关于表格标记,我们通常尝试使用给定标记给出答案(除非它开始无效)以防 OP 无法更改它,然后在可能的情况下留下建议以改进它。想象一下基于用户无法更改的修改标记的解决方案:(但是,在这种情况下它并不重要。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-08-06
  • 2020-12-12
  • 2021-08-26
  • 2017-05-13
  • 1970-01-01
  • 2013-01-10
  • 2017-03-30
相关资源
最近更新 更多