2017-04-21 10 views
4

JavaScriptオブジェクトをHTML ulリストファッションで表示しようとしています。 オブジェクトは、バイナリツリーを表し、この形式になっています。JavaScriptオブジェクトをulリストに再帰的に表示

{ 
    "val":2, 
    "l":{ 
     "val":1, 
     "l":{}, 
     "r":{} 
    }, 
    "r":{ 
     "val":4, 
     "l":{}, 
     "r":{ 
      "val":5, 
      "l":{}, 
      "r":{} 
     } 
    } 
} 

私は達成するために必要な結果がこれです:私は、結果のそれぞれの文字列を取得するために、ここにこのコードを書いた

<ul> 
    <li> 
     <a href="#">2</a> 
     <ul> 
      <li> 
       <a href="#">1</a> 
      </li> 
      <li> 
       <a href="#">4</a> 
       <ul> 
        <li> 
         <a href="#">5</a> 
        </li> 
       </ul> 
      </li> 
     </ul> 
    </li> 
</ul> 

しかし、それは正しい結果を生成しません。

function buildList(data){ 
    var html = ''; 
    if(data.val){ 
     if(data.l){ 
      html += '<ul>'; 
      html += buildList(data.l); 
     } 
     html += '<li>'; 
     html += '<a href="#">' + data.val + '</a>' 
     html += '</li>'; 
     if(data.r){ 
      html += buildList(data.r); 
      html += '</ul>'; 
     } 
    } 

    return html; 
} 

いずれかの推測または手がかりをいただければ幸いです。

+3

? –

+0

機能は正常に動作します。たぶん、ページに挿入しようとするか、コンソールを使用して戻り値を記録してみてください。 – gforce301

+1

その文字列で何をやっているのですか? – dobleUber

答えて

1

あなたが望むオブジェクトとDOMノードを構築することにより、動的な再帰的なアプローチを使用することができます。

function buildDOM(tree) { 
 
    function buildLI(node) { 
 
     var li = document.createElement('li'), 
 
      a = document.createElement('a'); 
 

 
     a.href = '#'; 
 
     a.appendChild(document.createTextNode(node.val)); 
 
     li.appendChild(a); 
 
     if (('l' in node) && ('val' in node.l) || ('r' in node) && ('val' in node.r)) { 
 
      li.appendChild(buildDOM(node)); 
 
     } 
 
     return li; 
 
    } 
 

 
    var ul = document.createElement('ul');     
 

 
    if (('l' in tree) && ('val' in tree.l)) { 
 
     ul.appendChild(buildLI(tree.l)); 
 
    } 
 
    if (('r' in tree) && ('val' in tree.r)) { 
 
     ul.appendChild(buildLI(tree.r)); 
 
    } 
 
    return ul; 
 
} 
 

 
var data = { val: 2, l: { val: 1, l: {}, r: {} }, r: { val: 4, l: {}, r: { val: 5, l: {}, r: {} } } }; 
 

 
document.body.appendChild(buildDOM({ r: data }));

0

ちょっとコードを並べ替えるだけです。ここでは実用的なソリューションです:

function buildList(data){ 
 
    var html = ''; 
 
    if(data.val){ 
 
     html += '<ul><li>'; 
 
     html += '<a href="#">' + data.val + '</a>' 
 
     html += '</li>'; 
 
     if(data.l){ 
 
      html += buildList(data.l); 
 
     } 
 
     if(data.r){ 
 
      html += buildList(data.r); 
 
      html += '</ul>'; 
 
     } 
 
    } 
 

 
    return html; 
 
} 
 

 
var resultDiv = document.getElementById('resultDiv'); 
 

 
var testData = 
 
    { 
 
     "val":2, 
 
     "l":{ 
 
      "val":1, 
 
      "l":{}, 
 
      "r":{} 
 
     }, 
 
     "r":{ 
 
      "val":4, 
 
      "l":{}, 
 
      "r":{ 
 
       "val":5, 
 
       "l":{}, 
 
       "r":{} 
 
      } 
 
     } 
 
    }; 
 
    
 
resultDiv.innerHTML = buildList(testData);
<p>Actual Result:</p> 
 
<div id="resultDiv">...</div> 
 

 
<hr> 
 

 
<p>Desired Result:</p> 
 
<ul> 
 
    <li> 
 
     <a href="#">2</a> 
 
     <ul> 
 
      <li> 
 
       <a href="#">1</a> 
 
      </li> 
 
      <li> 
 
       <a href="#">4</a> 
 
       <ul> 
 
        <li> 
 
         <a href="#">5</a> 
 
        </li> 
 
       </ul> 
 
      </li> 
 
     </ul> 
 
    </li> 
 
</ul>

0
var dom = buildList(yourObject); 
final(dom); 

function buildList(data){ 
    if(data.val){  
     var currentTag = document.createElement('li'); 
     var atag = document.createElement('a'); 
     atag.setAttribute("href", "#"); 
     atag.innerText = data.val; 
     currentTag.appendChild(atag); 
     if(JSON.stringify(data.l) != "{}" || JSON.stringify(data.r) != "{}"){   
      var ulTag = document.createElement('ul'); 
      if(JSON.stringify(data.l) != "{}"){ 
       ulTag.appendChild(buildList(data.l)); 
      } 
      if(JSON.stringify(data.r) != "{}"){ 
       ulTag.appendChild(buildList(data.r)); 
      } 
      currentTag.appendChild(ulTag); 
     } 
    } 

    return currentTag; 
} 

function final(body) { 
    body = document.createElement('ul').appendChild(body); 
} 
2

は、簡単なことでこれは、データの抽象化の少しlooooong道を行く状況です。 1つの関数でデータのすべての差異を処理しようとすると、単一のブランチifと他の副作用コードの大きなスパゲッティに直面します。

以下のデータ抽象化を使用して、複雑なロジックと条件を1つのif/elseステートメントに減らしました。私はコードをビットごとにステップよ、私は最後


は私が持ってしたくない希望的観測で実行可能なデモで一緒にそれをすべて出してあげますvalが{}かどうか、またはlrのいずれが有効な価値を持っているかどうかを考える(例)。これは私には意味がありません。私は何を書くのが大好きだが、このようなものです:

const makeTree = ({val, l, r}) => { 
    if (val === undefined) 
    return [] 
    else 
    return [Node('ul', Node('li', Link('#', val)), ...makeTree(l), ...makeTree(r))] 
} 

これは私達が私達の処分で2つのコンストラクタNodeLinkを前提としています。しかし、それらを掘り下げる前に、makeTreeは何があっても配列を返します。だから、私たちのために何とかこれをHTMLに組み込む素敵なユーザ向きの機能を考え出す必要があります。それはmakeMenuになります - すべてのそれは配列のうち、ルートノードを取り、これはまた、私たちは2つのノードタイプNodeLinkに利用できるように.toElemが必要であることを知っているのに役立ちます、それ

const makeMenu = data => 
    makeTree(data)[0].toElem() 

.toElem()を呼び出しません。それでいいのは、あなたが望むべき一歩があなたが構築しなければならない次のものを教えてくれるからです。


NodeLinkコンストラクタ

のは、今NodeLinkを強打してみましょう。彼らは非常に簡単です。 Nodeは、特定のtypeの一般的なHTML要素で、子要素が適用されます。それぞれの子どもには.toElemという方法もあると予想されます。 Linkはちょうどhrefといくつかのtextを取り、それに応じて属性を設定して要素を構成します。

const Node = (type, ...children) => ({ 
    toElem:() => { 
    const elem = document.createElement(type) 
    children.forEach(child => elem.appendChild(child.toElem())) 
    return elem 
    } 
}) 

const Link = (href, text) => ({ 
    toElem:() => { 
    const elem = document.createElement('a') 
    elem.setAttribute('href', href) 
    elem.textContent = text 
    return elem 
    } 
}) 

すべて一緒にそれを置くあなたが取得しているどのような結果

const Node = (type, ...children) => ({ 
 
    toElem:() => { 
 
    const elem = document.createElement(type) 
 
    children.forEach(child => elem.appendChild(child.toElem())) 
 
    return elem 
 
    } 
 
}) 
 

 
const Link = (href, text) => ({ 
 
    toElem:() => { 
 
    const elem = document.createElement('a') 
 
    elem.setAttribute('href', href) 
 
    elem.textContent = text 
 
    return elem 
 
    } 
 
}) 
 

 
const makeTree = ({val, l, r}) => { 
 
    if (val === undefined) 
 
    return [] 
 
    else 
 
    return [Node('ul', Node('li', Link('#', val)), ...makeTree(l), ...makeTree(r))] 
 
} 
 

 
const makeMenu = data => 
 
    makeTree(data)[0].toElem() 
 

 
const data = { "val": 2, "l": { "val": 1, "l": {}, "r": {} }, "r": { "val": 4, "l": {}, "r": { "val": 5, "l": {}, "r": {} } } } 
 

 
document.body.appendChild(makeMenu(data))

関連する問題