2017-06-10 10 views
0

私は巨大なjavascriptオブジェクトを順序付けられていないリストに変換するために1週間努力してきました。私は今は正しく機能していません。最初のレイヤーだけを返します。残りのそれdoesnt。私の解決策は、setTimeout(function、0)を使うことです。は大量のJSONをHTMLリストに再帰的に変換します

JSON形式:

{ 
"name": "", 
"value": { //JSON always start with these 2. content is inside this value key. 
    "randomname": { 
     "type": "list", 
     "value": { 
      "type": "int", //another type and value to that is in the array 
      "value": [26, 32, 25] 
     } 
    }, 
    "randomname": { 
     "type": "int", 
     "value": 5 
    }, 
    "randomname": { 
     "type": "string", 
     "value": "string or something" 
    }, 
    "randomname": { 
     "type": "compound", //compound types can be inside compound types can be inside compount types etc. 
     "value": { 
      "randomname": { 
       "type": "int", 
       "value": 6 

      }, 
      "randomname": { 
       "type": "int", 
       "value": 6 

      } 
     } 
    }, 
    "randomname": { 
     "type": "long", 
     "value": [0.0345034, 4.345345] 
    } 

} 

私が作ってみましたコード:

function readObject(el, data, boo) { 
    for(var ind in data) { 
     el.innerHTML += '<li>'; 
     if (boo) { 
      el.innerHTML += ind + ' - '; 
     } 
      console.log("another loop"); 
      switch (data[ind].type) { 
       case "compound": 
        el.innerHTML += data[ind].type + ' - '; 
        setTimeout(function(){ readObject(el,data[ind].value,false); el.innerHTML += '</li>';},0); 
        break; 
       case "string": 
        el.innerHTML += data[ind].type + ' - '; 
        el.innerHTML += data[ind].value; 
        callback(); 
        break; 
       case "int": 
        el.innerHTML += data[ind].type + ' - '; 
        el.innerHTML += data[ind].value; 
        callback(); 
        break; 
       case "long": 
        el.innerHTML += data[ind].type + ' - '; 
        el.innerHTML += data[ind].value[0] + ' - ' + data[ind].value[1]; 
        callback(); 
        break; 
       case "list": 
        el.innerHTML += data[ind].type + ' - '; 
        el.innerHTML += data[ind].value.type + ' - '; 
        setTimeout(function(){ readObject(el,listToObject(data[ind].value),false);el.innerHTML += '</li>'; },0); 
        break; 
      } 



      function callback() { 
       el.innerHTML += '</li>'; 
      } 
    } 
} 

(他のすべての型が文字列のと同じになります)

+0

日時: "ブラウザの凍結" - [リミットDOMアップデート](https://stackoverflow.com/documentation/javascript/1640/performance-tips/14978/limit-dom-updates#t=201706101834575306386) – Emissary

+0

@Emissaryありがとう、私は、ブラウザのフリーズも長い再帰によって引き起こされると思います。 – mrjvs

+0

ほとんどの場合、DOMの更新が増えただけです。 DOM操作は、比較的非常に遅いです。 –

答えて

1
を。

DOMの操作が遅いです。

また、コードには別の問題があります:setTimeoutを使用し、コールバックであなたが提供する変数indがコールバックの実行時に変更されることを参照すると、もしあれば望ましくない結果につながります。

コードではulタグは生成されず、liタグのみが生成されます。注意:関数の定義を提供していません。ですが、問題ありません(配列オブジェクトです)。ここで

はまた、「化合物」として、あなたはあまり些細なサブタイプのリストを持っている場合、とよく対処します実装です - 私は、サンプルデータの末尾に例を追加しました:

function objectToHtml(data, defaultType) { 
 
    var html = ''; 
 
    for (var ind in data) { 
 
     var item = data[ind], 
 
      type = defaultType || item.type, 
 
      value = defaultType ? item : item.value; 
 
     html += 
 
      '<li>\n' + 
 
      (defaultType ? '' : ind + ' - ' + type + ' - ') + 
 
      (type === "compound" ? objectToHtml(value) 
 
       : type === "list" ? value.type + ' - ' 
 
            + objectToHtml(value.value, value.type) 
 
       : type === "long" ? value.join(' - ') 
 
       : value) + 
 
      '</li>\n'; 
 
    } 
 
    return '<ul>\n' + html + '</ul>\n'; 
 
} 
 

 
// Sample data 
 
var data = { 
 
    "name": "", 
 
    "value": { 
 
     "randomname1": { 
 
      "type": "list", 
 
      "value": { 
 
       "type": "int", 
 
       "value": [26, 32, 25] 
 
      } 
 
     }, 
 
     "randomname2": { 
 
      "type": "int", 
 
      "value": 5 
 
     }, 
 
     "randomname3": { 
 
      "type": "string", 
 
      "value": "string or something" 
 
     }, 
 
     "randomname4": { 
 
      "type": "compound", 
 
      "value": { 
 
       "randomname5": { 
 
        "type": "int", 
 
        "value": 6 
 
       }, 
 
       "randomname6": { 
 
        "type": "int", 
 
        "value": 6 
 
       } 
 
      } 
 
     }, 
 
     "randomname7": { 
 
      "type": "long", 
 
      "value": [0.0345034, 4.345345] 
 
     }, 
 
     "randomname8": { 
 
      "type": "list", 
 
      "value": { 
 
       "type": "compound", 
 
       "value": [{ 
 
        "randomnameA": { 
 
         "type": "int", 
 
         "value": 7 
 
        }, 
 
        "randomnameB": { 
 
         "type": "int", 
 
         "value": 8 
 
        } 
 
       }, { 
 
        "randomnameC": { 
 
         "type": "int", 
 
         "value": 9 
 
        }, 
 
        "randomnameD": { 
 
         "type": "int", 
 
         "value": 10 
 
        } 
 
       }] 
 
      } 
 
     } 
 
    } 
 
}; 
 

 

 
tree.innerHTML = objectToHtml(data.value);
<div id="tree"></div>

+0

これは私の質問に完璧に、非常にコンパクトです。よくやった。 – mrjvs

1

私は「かどうか分かりません作成しようとしているHTML構造と完全に一致していますが、ニーズに合わせて変更するには十分近いはずです。

var convert = function(input) { 
 
    var out = ''; 
 
    out += '<ul>'; 
 
    for (k in input) { 
 
    var obj = input[k]; 
 
    out += '<li>' + k + ' - ' + obj.type + ' - '; 
 
    switch(obj.type) { 
 
     case "compound": 
 
     // recurse: 
 
     out += convert(obj.value); break; 
 
     case "long": 
 
     out += obj.value.join(' - '); break; 
 
     case "list": 
 
     out += obj.value.type + ' - '; 
 
     out += obj.value.value.join(' - '); break; 
 
     default: 
 
     // looks like all the other cases are identical: 
 
     out += obj.value; 
 
    } 
 
    out += '</li>'; 
 
    } 
 
    out += '</ul>'; 
 
    return out; 
 
} 
 

 
var data = { 
 
    "name": "", 
 
    "value": { 
 
    "randomname1": { 
 
     "type": "list", 
 
     "value": { 
 
     "type": "int", 
 
     "value": [26, 32, 25] 
 
     } 
 
    }, 
 
    "randomname2": { 
 
     "type": "int", 
 
     "value": 5 
 
    }, 
 
    "randomname3": { 
 
     "type": "string", 
 
     "value": "string or something" 
 
    }, 
 
    "randomname4": { 
 
     "type": "compound", 
 
     "value": { 
 
     "randomname5": { 
 
      "type": "int", 
 
      "value": 6 
 
     }, 
 
     "randomname6": { 
 
      "type": "int", 
 
      "value": 6 
 
     } 
 
     } 
 
    }, 
 
    "randomname7": { 
 
     "type": "long", 
 
     "value": [0.0345034, 4.345345] 
 
    } 
 
    } 
 
}; 
 

 
document.getElementById('output').innerHTML = convert(data.value);
<div id="output"></div>

を単離した文書フラグメントとして構築するのではなく:

最速のアプローチではなく、増分DOM操作を行うための、単一の文字列を作成し、DOMにドロップすることです単一のHTML文字列は、この場合、約25%遅くなります。https://jsperf.com/tree-test-fragment-vs-string/1

しかし、少し遅くすれば、遅い方法ではあなたのsetTimeoutトリックを使用して各レベルの再帰を延期してください。そうすれば、非常に大きなツリーを描画しようとしている間、ブラウザ(1つの希望)がフリーズすることはありません。

ここで、再帰は別々の関数で処理されるため、それぞれのsetTimeoutは正しいデータとDOMノードで処理されます(同じ関数内ですべてを実行しようとすると、反復によって新しいデータで変数が上書きされます)。時間のsetTimeout火災は - これはあなたの元のコードが適切に再帰されなかった理由の一部であった)、私はこれが動作していることを実証するデータにいくつかのより深い化合物の種類を追加しました:

var convert = function(input) { 
 
    var fragment = document.createDocumentFragment(); 
 
    var ul = document.createElement('ul'); 
 
    fragment.appendChild(ul); 
 

 
    for (k in input) { 
 
    var obj = input[k]; 
 
    var li = document.createElement('li'); 
 
    var txt = k + ' - ' + obj.type + ' - '; 
 
    if (obj.type === 'compound') { 
 
     li.innerHTML = txt; 
 
     recurse(li, obj.value); // acts as a closure for these vars 
 
    } else { 
 
     switch (obj.type) { 
 
     case "long": 
 
      txt += obj.value.join(' - '); 
 
      break; 
 
     case "list": 
 
      txt += obj.value.type + ' - '; 
 
      txt += obj.value.value.join(' - '); 
 
      break; 
 
     default: 
 
      txt += obj.value; 
 
     } 
 
     li.innerHTML = txt; 
 
    } 
 
    ul.appendChild(li); 
 
    } 
 
    return fragment; 
 
} 
 

 
var recurse = function(li, d) { 
 
    window.setTimeout(function() { 
 
    li.appendChild(convert(d)); 
 
    }, 1); 
 
} 
 

 
var data = { 
 
    "name": "", 
 
    "value": { 
 
    "randomname1": { 
 
     "type": "list", 
 
     "value": { 
 
     "type": "int", 
 
     "value": [26, 32, 25] 
 
     } 
 
    }, 
 
    "cptest1": { 
 
     "type": "compound", 
 
     "value": { 
 
     "x": { 
 
      "type": "int", 
 
      "value": 2 
 
     }, 
 
     "cptest2": { 
 
      "type": "compound", 
 
      "value": { 
 
      "y": { 
 
       "type": "int", 
 
       "value": 2 
 
      }, 
 
      "z": { 
 
       "type": "int", 
 
       "value": 3 
 
      } 
 
      } 
 
     }, 
 
     } 
 
    }, 
 
    "randomname3": { 
 
     "type": "string", 
 
     "value": "string or something" 
 
    }, 
 
    "randomname4": { 
 
     "type": "compound", 
 
     "value": { 
 
     "randomname5": { 
 
      "type": "int", 
 
      "value": 6 
 
     }, 
 
     "randomname6": { 
 
      "type": "int", 
 
      "value": 6 
 
     } 
 
     } 
 
    }, 
 
    "randomname7": { 
 
     "type": "long", 
 
     "value": [0.0345034, 4.345345] 
 
    } 
 
    } 
 
}; 
 

 
document.getElementById('output').appendChild(convert(data.value));
<div id="output"></div>

関連する問題