在纯JavaScript中,JSON对象是 HTML table

分享于 

19分钟阅读

Web开发

  繁體 雙語

目录

简介

输入JSON数据格式定义/需求

输入参数和返回值

代码说明

函数的 完整代码

下载源代码

历史

简介

使用JSON对象填充 table的任务似乎微不足道。 实际上,当对象( 键集合)的结构已知时。
但是如果我们希望函数是通用的,并且能够处理未知的预先构造的"table 行"对象,该怎么办? 这将需要开发者更多的努力。
让我们更远一些。如果我们想要具有通用功能,还可以执行以下操作:

  • 在它的字符串表示形式或者( 已经解析) 对象窗体中接受输入 JSON。
  • 以不同格式接受输入 JSON,特别是作为对象或者具有这里 array 值的对象作为键的值。
  • 填充现有 table 或者创建,填充和返回新的。
  • 向 table的各种现有节添加行或者替换节内容的现有部分
  • 将大多数输入参数视为可选的。

在这里我们将构建一个函数,希望在遇到 table 对象的任务时,我们需要唯一的函数。

输入JSON数据格式定义/要求

输入数据的中心元素是JSON对象("table 行"对象),它的键/值对为 table 列。 我们目标是填充一个 table。 因此,我们将处理对象的一组。 由于 JSON是基于两种结构构建的,所以我们需要通用函数来处理它们。
输入JSON数据的要求是:

- 结构JSON输入的格式应为以下两种格式之一:

  • "table 行"对象的array
  • 对象( 名称/值对),其中( 首) 键的值是"table 行"对象的array

- 所有"table 行"对象都具有相同的键集合,但在同一顺序下不需要

输入参数和返回值

为了向函数添加通用性,让我们创建输入参数列表,该列表可以能覆盖 table 数据的最实际任务。
完整的参数列表,以便它们在函数调用中出现的方式及它的解释提供了 below。 除 aJSON 之外的所有参数都是可选的,并且具有默认值。 可选参数必须在参数列表的末尾形成一个组。 换句话说,如果 aTable 参数丢失,则缺少所有参数。

  • aJSON ( 必需参数)

以下结构中的字符串表示或者解析的JSON对象:
-"table 行"对象的array
- 具有第一个( 其他被忽略) key-value 对的对象,其中值是"table 行"对象的array
注意,"table 行"对象必须具有相同的键集。

  • aAddHead

- false ( 默认情况) - 不改变头部的内容
- true - 带有"table 行"json对象键的窗体"一行"头,如果有的话,替换现有的头部内容

  • aTable

- null ( 默认情况) - 函数将创建和返回单个 body 节和可以能头( 请参见 aAddHead 上面 )的table 对象
- 现有 table 对象- 将以其他输入参数控制的方式填充该 table

  • aClearSectionToFill

- false ( 默认情况) - 将添加到要填充的table 部分的末尾。
- true - 在填充之前,将从分区中删除所有现有行
- 如果创建新的table,则忽略此参数

  • aSectionToFill

- 空( 默认情况) - 将填充最后一个 tBody 节,如果不存在则创建
- 特定的TableSectionObj - 将填充 table 部分。 通常( 其中之一) body,但理论上可以是脚或者头。
- 如果创建新的table ( 将填充新的单个 body ),则忽略这里参数

  • aClearEntireTable

- false ( 默认情况下)
- true - 在填充 table 之前,从 table的所有节删除行,而不删除节
- 如果创建新的table,则忽略此参数

  • aClearHead

- false ( 默认情况下)
- true - 移除不移除节的tHead 节中的所有行( 如果有的话)
- 如果创建 aClearEntireTable == true 或者 AddHead == true 或者新 table,则忽略此参数

  • aClearAllBodies

- false ( 默认情况下)
- true - 从所有 tBody 节移除所有行( 如果有的话),而不删除节
- 如果创建 aClearEntireTable == true 或者新 table,则忽略此参数

  • aClearFoot

- false ( 默认情况下)
- true - 移除不移除节的tFoot 节中的所有行( 如果有的话)
- 如果创建 aClearEntireTable == true 或者新 table,则忽略此参数

  • Return Value

- 如果填充现有 table,则函数返回相同的table 对象,该对象作为输入参数 aTable 传递
- 如果创建并填充新的table,则函数返回新创建的table 对象。

代码解释

处理输入参数

首先,让我们确保指定了必需的参数。

if (!Boolean(aJSON))
 throw"jsonObjToHtmlTable: Required parameter aJSON is not specified";

我们将把输入参数转换为局部变量集,这些变量实际上用来控制过程。 翻译逻辑还为可选参数提供默认值。
前两种是明显的:

var addHead = Boolean(aAddHead);var createNewTable =!Boolean(aTable);

下一组与清除 table 或者它的节有关。 显然,我们不需要清除新创建的table。 另外,我们不需要明确处理整个 table 清除的代码,因为我们将该操作看作"清除头部"。"清除所有实体"和"清除脚"的"求和"。

var clearSectionToFill =!createNewTable && Boolean(aClearSectionToFill);var clearTable =!createNewTable && Boolean(aClearEntireTable);var clearHead =!createNewTable && (clearTable || addHead || Boolean(aClearHead));var clearAllBodies =!createNewTable && (clearTable || Boolean(aClearAllBodies));var clearFoot =!createNewTable && (clearTable || Boolean(aClearFoot));

最后一组与 table 对象及其节元素有关。 其中一些可以得到空值,而这些情况会相应地处理。

var tblToFill = createNewTable? document.createElement("table") : aTable;var tblHead = tblToFill.tHead;var tblFoot = tblToFill.tFoot;var tblBodies = tblToFill.tBodies;var sectionToFill = createNewTable? null : aSectionToFill;

我们想知道必须将 table 行的确切部分添加到。 如果此时没有指定 sectionToFill,那么默认情况下,我们将使用最后一个可用 body 节创建一个如果不存在。

if (!sectionToFill) {
 if (!(Boolean(tblBodies) && (tblBodies.length> 0))) {
 tblToFill.appendChild(document.createElement("TBODY"));
 tblBodies = tblToFill.tBodies;
 }
 sectionToFill = tblBodies[tblBodies.length - 1];
}

避免嵌套函数

我们需要清除( delete 行) 各个 table 部分的能力。 直接的解决方案将是嵌套函数用法。 尽管通常会遇到建议,但是由于经常会损害性能和/或者内存使用情况,因此在javascript中避免嵌套函数。 尽管我们的案例似乎不是"有害的"的一个,但是我们仍然会遵循这个建议,但是使用它的他解决方案。 让我们把这个子函数定义为 jsonObjToHtmlTable 函数对象的一个方法:

if (!jsonObjToHtmlTable.clearTableSection)
 jsonObjToHtmlTable.clearTableSection = 
 function (aTblSection) {
 for (var i = aTblSection.rows.length - 1; i> = 0; i--)
 aTblSection.deleteRow(i);
 };

清除 table 或者它的节

在实际 table 填充之前,如果需要,我们需要清除 table 或者它的特定部分。 所有可能的清除类型都定义在输入参数解释阶段。 现在,如果请求了某些特定类型的清除,并且 table的相应部分存在,那么我们将清除它。

if (clearHead && Boolean(tblHead))
 jsonObjToHtmlTable.clearTableSection(tblHead);if (clearAllBodies && Boolean(tblBodies) && (tblBodies.length> 0))
 for (var i = tblBodies.length - 1; i> = 0; i--)
 jsonObjToHtmlTable.clearTableSection(tblBodies[i]);if (clearFoot && Boolean(tblFoot))
 jsonObjToHtmlTable.clearTableSection(tblFoot);if (clearSectionToFill)
 jsonObjToHtmlTable.clearTableSection(sectionToFill);

处理字符串或者对象输入

我们希望我们的函数是通用的,并且接受不同类型的输入对象。 由于处理 JSON,我们可以考虑输入对象的两种可以能性,特别是文本/string格式或者已经解析的javascript对象。 因此让我们检查输入是字符串并解析它还是按其他方式使用它:

var inputJSObj = (Object.prototype.toString.call(aJSON) === "[object String]")?
 JSON.parse(aJSON) : aJSON;

使用 Object.keys() 方法

正如已经指出的,我们希望处理具有未知结构的"table 行"对象,换句话说,未知的属性/键及它的名称。 但是显然我们仍然需要访问属性/键值。 返回对象名的给定属性/键的array的Object.keys(obj) 方法在这里很有用。 考虑到并非所有浏览器都支持这里方法,如果在 IE 9前,让我们自己处理这种情况:

if(!Object.hasOwnProperty("keys")){
 Object.keys = function(aObj){
 var keyNameArray = [];
 for (keyName in aObj){
 if (aObj.hasOwnProperty(keyName)){
 keyNameArray[keyNameArray.length] = keyName;
 }
 }
 return keyNameArray;
 };
}

处理 array 或者键/值输入

下一步是确定输入对象的结构。 由于根据先前制定的需求输入可以是 array 或者"键/值"对格式,让我们检查它是否为 array,并使用它作为( 首) 键的值,这应该是 array 值。

var allRowsAsArrayOfObjects = (Object.prototype.toString.call(inputJSObj) === "[object Array]")?
 inputJSObj : inputJSObj[Object.keys(inputJSObj)[0]];

现在我们有了 array的对象,它们将形成 table 行。 如果这个不是空的,我们将继续执行剩下的步骤, allRowsAsArrayOfObjects.length> 0 )。
由于我们要求所有"table 行"对象具有相同的键集,所以我们可以从任何对象( 特别是第一个对象) 获取集合:

var rowKeyNames = Object.keys(allRowsAsArrayOfObjects[0]);

table 节的头标题

如果请求 table 成形头,并且 tHead 部分已经存在,则应该已经清除了前面的( 请参阅 clearHead的逻辑)。 如果 tHead 不存在,那么我们将创建一个。 之后我们只需要向头部添加一行,并用 上面 rowKeyNames array 中的值填充它的单元格。 只有一个不便,因为 tHead.insertCell() 方法创建 <td> 单元格,我们需要 <th> 单元格,我们需要使用较长的代码:

var headRow, headRowCell;if (addHead) {
 tblHead = tblHead? tblHead : tblToFill.createTHead();
 headRow = tblHead.insertRow(-1);
 for (var j = 0; j <rowKeyNames.length; j++) {
 headRowCell = document.createElement("th");
 headRowCell.appendChild(document.createTextNode(rowKeyNames[j]));
 headRow.appendChild(headRowCell);
 }
}

添加数据行

finally 我们已经准备好用数据行填充 table。 在先前的阶段确定了哪些准确的table 截面被填充,如果需要的话,截面被清除。 其余的是简单的。对于每个"table 行"对象,向创建行的必要单元格添加行并指定它们的值。 我们使用 <td> 单元创建 <th> 单元格,以便使用相同的方法,但是在这里我们可以使用 insertCell()

var oneRowAsObject, tableRow, rowCell;for (var i = 0; i <allRowsAsArrayOfObjects.length; i++) {
 oneRowAsObject = allRowsAsArrayOfObjects[i];
 tableRow = sectionToFill.insertRow(-1);
 for (var j = 0; j <rowKeyNames.length; j++) {
 rowCell = document.createElement("td");
 rowCell.appendChild(document.createTextNode(oneRowAsObject[rowKeyNames[j]]));
 tableRow.appendChild(rowCell);
 }
}

函数的完整代码

完整的代码,包括所有讨论过的上面 Fragment,都提供了 below。

/* Copyright (c) 2015 Vladimir Nikitenko - Code Project Open License (CPOL) */function jsonObjToHtmlTable(aJSON, aAddHead, aTable, aClearSectionToFill, aSectionToFill,
 aClearEntireTable, aClearHead, aClearAllBodies, aClearFoot) {
 if (!Boolean(aJSON))
 throw"jsonObjToHtmlTable: Required parameter aJSON is not specified";
 var addHead = Boolean(aAddHead);
 var createNewTable =!Boolean(aTable);
 var clearSectionToFill =!createNewTable && Boolean(aClearSectionToFill);
 var clearTable =!createNewTable && Boolean(aClearEntireTable);
 var clearHead =!createNewTable && (clearTable || addHead || Boolean(aClearHead));
 var clearAllBodies =!createNewTable && (clearTable || Boolean(aClearAllBodies));
 var clearFoot =!createNewTable && (clearTable || Boolean(aClearFoot));
 var tblToFill = createNewTable? document.createElement("table") : aTable;
 var tblHead = tblToFill.tHead;
 var tblFoot = tblToFill.tFoot;
 var tblBodies = tblToFill.tBodies;
 var sectionToFill = createNewTable? null : aSectionToFill;
 if (!sectionToFill) {
 if (!(Boolean(tblBodies) && (tblBodies.length> 0))) {
 tblToFill.appendChild(document.createElement("TBODY"));
 tblBodies = tblToFill.tBodies;
 }
 sectionToFill = tblBodies[tblBodies.length - 1];
 }
 if (!jsonObjToHtmlTable.clearTableSection)
 jsonObjToHtmlTable.clearTableSection = 
 function (aTblSection) {
 for (var i = aTblSection.rows.length - 1; i> = 0; i--)
 aTblSection.deleteRow(i);
 };
 if (clearHead && Boolean(tblHead))
 jsonObjToHtmlTable.clearTableSection(tblHead);
 if (clearAllBodies && Boolean(tblBodies) && (tblBodies.length> 0))
 for (var i = tblBodies.length - 1; i> = 0; i--)
 jsonObjToHtmlTable.clearTableSection(tblBodies[i]);
 if (clearFoot && Boolean(tblFoot))
 jsonObjToHtmlTable.clearTableSection(tblFoot);
 if (clearSectionToFill)
 jsonObjToHtmlTable.clearTableSection(sectionToFill);
 var inputJSObj, allRowsAsArrayOfObjects, oneRowAsObject, rowKeyNames;
 var headRow, headRowCell, tableRow, rowCell;
 if(!Object.hasOwnProperty("keys")){
 Object.keys = function(aObj){
 var keyNameArray = [];
 for (keyName in aObj){
 if (aObj.hasOwnProperty(keyName)){
 keyNameArray[keyNameArray.length] = keyName;
 }
 }
 return keyNameArray;
 };
 }
 inputJSObj = (Object.prototype.toString.call(aJSON) === "[object String]")? 
 JSON.parse(aJSON) : aJSON;
 allRowsAsArrayOfObjects = (Object.prototype.toString.call(inputJSObj) === "[object Array]")?
 inputJSObj : inputJSObj[Object.keys(inputJSObj)[0]];
 rowKeyNames = [];
 if (allRowsAsArrayOfObjects.length> 0){
 rowKeyNames = Object.keys(allRowsAsArrayOfObjects[0]);
 if (addHead) {
 tblHead = tblHead? tblHead : tblToFill.createTHead();
 headRow = tblHead.insertRow(-1);
 for (var j = 0; j <rowKeyNames.length; j++) {
 headRowCell = document.createElement("th");
 headRowCell.appendChild(document.createTextNode(rowKeyNames[j]));
 headRow.appendChild(headRowCell);
 }
 }
 for (var i = 0; i <allRowsAsArrayOfObjects.length; i++) {
 oneRowAsObject = allRowsAsArrayOfObjects[i];
 tableRow = sectionToFill.insertRow(-1);
 for (var j = 0; j <rowKeyNames.length; j++) {
 rowCell = document.createElement("td");
 rowCell.appendChild(document.createTextNode(oneRowAsObject[rowKeyNames[j]]));
 tableRow.appendChild(rowCell);
 }
 }
 }
 return tblToFill;
}

下载源代码

下面的源代码都是一个zip文件,可以在本页的顶部下载:

  • xml文件中JSON对象到HTML函数的代码。
  • jsonObjToHtmlTable_Test.html 文件中的测试/演示应用程序。 这个应用程序实际上是html页面,允许演示和测试函数的所有特性。 它引用包含测试函数的上面 外部文件,假定它位于同一目录中。

历史

版本 1.0 ( 2015-01-25 )

  • 第一个版本

JAVA  Javascript  对象  tab    Html表格  
相关文章