4

以下のようなオブジェクトがあります。

var obj = {
   a : {
      x : 1,
      y : 2,
      z : 3
   },
   b : {
      x : 1,
      y : 2,
      z : 3
   }
}

これで、次のテーブルを生成したいと思います。フォーマットを以下に示します

http://jsfiddle.net/gD87t/

オブジェクトから要素を取得しようとしていますが、追加しようとしていますが、rowSpan 値と混同されています

var tr = document.createElement('tr');
for(var i in obj){
   var td = document.createElement('td');
   td.rowSpan = ? // Here I am getting confused.
}

テンプレート エンジンは私の問題を解決できますか? これを行う最善の方法は何ですか?

4

7 に答える 7

4

Here's one way of doing it with a recursive function in pure js:

function addObjectToTable(table, obj, tr) {
  var rows = 0;
  for (key in obj) {
    if (tr == null) {
      tr = document.createElement('tr');
      table.appendChild(tr);
    }  

    var td = document.createElement('td');
    td.textContent = key;
    tr.appendChild(td);

    var value = obj[key];
    if (typeof value != 'object') {
      var td = document.createElement('td');
      td.textContent = value;
      tr.appendChild(td);
      rows += 1;
    }
    else {
      var subrows = addObjectToTable(table, value, tr);
      td.setAttribute('rowspan',subrows);
      rows += subrows;
    }

    tr = null;
  }
  return rows;
}

Which would be called like this:

var table = document.createElement('table');
addObjectToTable(table,obj);
document.body.appendChild(table);

Note that when first called, the tr parameter is null, since we always have to create a new row at the top level. When the function is called recursively though, the tr parameter is passed in from the upper level since lower levels will intially be adding to the the row of their parent object.

The function returns the number of rows added, so when it is called recusively the caller will know what to set the rowspan value to.

Fiddle link

于 2013-06-23T17:44:36.620 に答える
3

回覧を処理する答えが見つかりませんでした。また、不要な DOM 書き込みなしでこれを行うことにしました。また、OPが要求した正確なマークアップには従いませんでした。これは、このような再帰操作にはネストテーブルの方が便利であり、同じ視覚的目的に近いと感じたためです。

だから、ここに私が作成した関数があります:

function dataToTable (data) {
    var storage = [];
    return (function buildTable (data) {
        var table = '<table><tbody>';
        var name, value;
        // Add the object/array to storage for cirular detection.
        storage.push(data);
        for (name in data) {
            value = data[name];
            table += '<tr><td>' + name + '</td><td>';
            // If the value is an object we've put in storage (circular)
            if (storage.indexOf(value) !== -1) {
                table += '<em>Circular</em>';
            } else if (typeof value === 'object') {
                table += buildTable(value);
            } else {
                table += value;
            }
            table += '</td></tr>';
        }
        return table + '</tbody></table>';
    }(data));
}

テストに使用したオブジェクトは次のとおりです。

var obj = {
   a : {
      x : 1,
      y : 2,
      z : 3
   },
   b : {
      x : 1,
      y : 2,
       z : {
           test1: 0,
           test2: {
               test3: 1,
               test4: ['a','b','c']
           }
       }
   }
};
obj.c = obj;
obj.b.z.test2.test4.push(obj.a);

この関数は、このオブジェクトを HTML テーブルに変換します。テーブルをどうするかはあなた次第です。私のフィドルでは、DOM を使用してテーブルを DIV (document.getElementById) に追加しました。

http://jsfiddle.net/5RhXF/1/

私の実装が明確になることを願っています。

アップデート::

これを jQuery ライブラリでテストすることにしましたが、うまくいきました。ただし、関数は、テキストに適した形式のない toString 値として出力されていました..これは理にかなっていますが、あまり役に立ちません。したがって、これは、フレームワーク/ライブラリなどの API を調べるための簡単で便利な方法だと思います。そのため、関数の構文強調表示用に prettify を追加し、テーブル ジェネレーターに関数の型チェックを追加し、prettify ボックスの周囲の境界線を取り除くためのクイック クラスを追加しました (テーブル セルには既に境界線があるため)。 . ソースの読み取り/デバッグ用に設計されたバージョンに興味がある場合は、フィドルを次に示します。

http://jsfiddle.net/5RhXF/7/

于 2013-06-23T15:47:36.750 に答える
1
var table = document.createElement('table');
var i, j;
var row, cell;
for(i in obj) {
    if(obj.hasOwnProperty(i)) {
        var row = document.createElement('tr');
        var cell = document.createElement('td');
        cell.rowSpan = Object.keys(obj[i]).length;
        cell.innerText = i;
        row.appendChild(cell);
        for(j in obj[i]) {
            if(obj[i].hasOwnProperty(j)) {
                cell = document.createElement('td');
                cell.innerText = j;
                row.appendChild(cell);
                cell = document.createElement('td');
                cell.innerText = obj[i][j];
                row.appendChild(cell);
                table.appendChild(row);
                row = document.createElement('tr');
            }
        }
    }
}
document.body.appendChild(table);

もちろん、jQuery では冗長に見えません。しかし、プレーンDOMでやりたいように見えました。

ウォーキングを見る

于 2013-06-22T12:42:51.710 に答える
1

の値はrowspan、内部オブジェクトのプロパティの数です。関数を使用Object.keysしてオブジェクトのキーのリストを取得し、そのlengthプロパティを使用してプロパティの数を決定できます。

for(var i in obj){
   var td = document.createElement('td');
   td.rowSpan = Object.keys(obj[i]).length;
}
于 2013-06-19T10:28:29.713 に答える
0

質問と同じように使用document.createElementしたい場合、最も簡単な方法はおそらく次のとおりです。

function generateTable(o) {
    var table, tr, td, i, j, l, keys;

    table = document.createElement('table')

    for(i in o){
        tr = document.createElement('tr');
        table.appendChild(tr);
        td = document.createElement('td');
        keys = Object.keys(o[i]);
        td.rowSpan = keys.length;
        td.textContent = i;
        tr.appendChild(td);
        x=0;

        for(j=0;j<keys.length;j++) {
            if(j) {
                tr = document.createElement('tr');
                table.appendChild(tr);            
            }
            td = document.createElement('td');
            td.textContent = keys[j];
            tr.appendChild(td);
            td = document.createElement('td');
            td.textContent =o[i][keys[j]];
            tr.appendChild(td);
        }
    }
    return table;
}

警告:Object.keys古いブラウザーでは使用できないため、次のようなポリフィルが必要になります。

( MOZILLA DEVELOPER NETWORKから取得)

if (!Object.keys) {
  Object.keys = (function () {
    var hasOwnProperty = Object.prototype.hasOwnProperty,
        hasDontEnumBug = !({toString: null}).propertyIsEnumerable('toString'),
        dontEnums = [
          'toString',
          'toLocaleString',
          'valueOf',
          'hasOwnProperty',
          'isPrototypeOf',
          'propertyIsEnumerable',
          'constructor'
        ],
        dontEnumsLength = dontEnums.length;

    return function (obj) {
      if (typeof obj !== 'object' && typeof obj !== 'function' || obj === null) throw new TypeError('Object.keys called on non-object');

      var result = [];

      for (var prop in obj) {
        if (hasOwnProperty.call(obj, prop)) result.push(prop);
      }

      if (hasDontEnumBug) {
        for (var i=0; i < dontEnumsLength; i++) {
          if (hasOwnProperty.call(obj, dontEnums[i])) result.push(dontEnums[i]);
        }
      }
      return result;
    };
  })();
}

別の方法として、ほとんどのケースをうまくカバーするもっと単純なポリフィルがあります:

トークン投稿から取得)

if (!Object.keys) Object.keys = function(o) {
  if (o !== Object(o))
    throw new TypeError('Object.keys called on a non-object');
  var k=[],p;
  for (p in o) if (Object.prototype.hasOwnProperty.call(o,p)) k.push(p);
  return k;
}

ここで実際のフィドルを見ることができます: http://jsfiddle.net/uyJv2/

于 2013-06-26T21:21:41.203 に答える