2010-12-31 6 views
2

ich die folgenden Codes geschrieben haben, ist der Zweck dieser Codes ein <ul> von einigen JavaScript Node-Objekte zu erzeugen:eine ungeordnete Liste von JavaScript-Knoten Generieren von Objekten

<html> 

<body> 
<div id='content'></div> 
<script type='text/javascript'> 

      function node(name,parent){ 
       this.name=name; 
       this.parent=parent; 
       this.level=function(){ 
        if(this.parent==null) 
         return 0; 
        return this.parent.level()+1;      
       } 
       this.childs=new Array(); 
      } 

      //create a rootNode, having no parent 
      var rootNode=new node('AAA',null); 

      //create node1 and add it to the child of rootNode 
      var node1=new node('BBB',rootNode); 
      rootNode.childs.push(node1); 

      //create node2 and add it to the child of rootNode 
      var node2=new node('CCC',rootNode); 
      rootNode.childs.push(node2); 

      //create node3 and add it to the child of node1 
      var node3=new node('DDD',node1); 
      node1.childs.push(node3); 

      //create node4 and add it to the child of node1 
      var node4=new node('EEE',node1); 
      node1.childs.push(node4); 

      //create node5 and add it to the child of node2 
      var node5=new node('FFF',node2); 
      node2.childs.push(node5); 

      function getTreeHTML(node,html){ 

       if(node.level()==0) 
        html+='<ul>'; 

       html+='<li>'; 
       html+=node.name; 
       if(node.childs.length > 0){ 
        html+='<ul>'; 
        for(var i in node.childs){ 
         html+=getTreeHTML(node.childs[i],html); 
        } 
        html+='</ul>'; 
       } 
       html+='</li>'; 

       if(node.level()==0) 
        html+='</ul>'; 
       return html; 
      } 

      var treeHTML=getTreeHTML(rootNode,''); 
      document.getElementById('content').innerHTML=treeHTML; 
</script> 
</body> 

</html> 

Unter rootNode, zwei unmittelbar untergeordneten Knoten gibt es Für diese zwei Kindknoten sollte einer von ihnen zwei Kinder haben und ein anderer sollte ein Kind haben. Ich vermute, dass es einen logischen Fehler in der getTreeHTML() Funktion gibt, aber ich kann einfach nicht herausfinden, was es ist, fühlen Sie sich frei, die Codes auf http://htmledit.squarefree.com/ einzufügen, dann können Sie schnell sehen, was ich meine.

Vielen Dank an euch alle.

+0

FYI, Plural von Kind Kinder, nicht Childs :) – Psytronic

+0

@Psytronic Danke. Ich werde nächstes Mal Kinder benutzen. :) – bobo

Antwort

4

Das Problem ist hier:

html+=getTreeHTML(node.childs[i],html); 

Sie enden - Hinzufügen der HTML-String zweimal, weil in der Funktion, die Sie mit dem HTML-String anhängen übergeben, aber dann verwenden Sie einen Anfügevorgang mit dem, was es auch zurückgibt. Wenn Sie es auf eine dieser Einstellung ändern, es funktioniert gut:

html=getTreeHTML(node.childs[i],html); 
html+=getTreeHTML(node.childs[i],''); 

Off-topic: Einige Vorschläge/Empfehlungen/Beobachtungen, wenn Sie daran interessiert sind; keiner der unten soll kritisch, nur hilfreich sein:

  1. Anstatt Strings verketten, es funktioniert in der Regel schneller aus, wenn Sie eine Reihe von Zeichenfolgen in einem Array aufbauen und dann eine join('') nutzen sie alle zusammen stellen in eine Zeichenfolge, wenn du fertig bist.
  2. Standard Praxis (die Sie frei sind zu ignorieren!) Ist Konstruktor Funktionen wie node zunächst capped (Node), um sie von Nicht-Konstruktor Funktionen zu unterscheiden.
  3. Jedes Ihrer node Objekte erhält seine eigene Kopie der level Funktion, die nicht in Ihrem Code erforderlich ist. Sie können alle teilen einelevel Funktion, wie folgt aus:

    function node(name,parent){ 
        this.name=name; 
        this.parent=parent; 
        this.childs=new Array(); 
    } 
    node.prototype.level = function() { 
        if(this.parent==null) 
         return 0; 
        return this.parent.level()+1;      
    } 
    
  4. In Englisch, der Plural von "Kind" ist "Kinder" (es ist unregelmäßig).

  5. Die Verwendung von for..in zum Durchlaufen von Array-Indizes, wie in Ihrer for(var i in node.childs){, ist heikel und technisch inkorrekt, es sei denn, Sie treffen ein paar Vorsichtsmaßnahmen in der Schleife; es wird fehlschlagen, wenn Sie etwas Interessantes mit Ihren Arrays machen, wie mehr Metadaten hinzuzufügen (Arrays sind nur Objekte, Sie können ihnen beliebige Eigenschaften hinzufügen und Bibliotheken fügen manchmal Eigenschaften zu Array.prototype hinzu, um Browserdifferenzen auszugleichen, die Mist machen werden eine naive for..in Schleife). Details hier: Myths and realities of for..in
  6. Sie können this.childs=new Array(); als this.childs=[]; schreiben, wenn Sie mögen; Sie haben genau den gleichen Effekt.
  7. Unabhängig davon, wo Sie Ihre var-Anweisung in Ihren Code setzen, wird sie am Anfang der Funktion wirksam (oder am Anfang des globalen Bereichs, wenn var global ist).Ich denke, dass ich ein bisschen alleine damit bin, aber ich mag es nicht, wenn mein Code ein bisschen irreführend ist, um Maintainer zu programmieren, also setze ich immer die var s nach oben. Mehr hier Poor misunderstood var. So zum Beispiel:

    // This series of statements 
    doSomething(); 
    doSomethingElse(); 
    var a = new Foo(); 
    doAnotherThing(); 
    
    
    // ...is *exactly* identical to: 
    var a; 
    doSomething(); 
    doSomethingElse(); 
    a = new Foo(); 
    doAnotherThing(); 
    
  8. eine Funktion auf node empfehlen, die ein Kind schafft und hakt es nach oben, so vermeiden Sie die Möglichkeit der parent gesetzt wird, aber dann das Kind zu dem falschen childs Array (oder nicht hinzugefügt überhaupt).

  9. Mit null zu meinen, "kein Elternteil" ist in Ordnung, aber undefined ist eigentlich ein bisschen einfacher zu arbeiten.
  10. Sie können an einigen Stellen die Leistung von JavaScript's Curiously-Powerful OR Operator (||) verwenden. Sie sehen dies ein Los in JavaScript-Code. if Aussagen sind total gut, aber ich dachte, es ist erwähnenswert, weil es so üblich ist.
  11. Hosenträger sind wirklich deine Freunde, auch wenn sie nicht notwendig sind.

Wenn man all das und ein paar kleinere Dinge zusammen:

var rootNode, node1, node2; 

function Node(name, parent){ 
    this.name = name; 
    this.parent = parent; // undefined if none 
    this.children = []; 
} 
Node.prototype.level = function(){ 
    return this.parent ? this.parent.level() + 1 : 0; 
}; 
Node.prototype.addChild = function(name) { 
    var child; 

    child = new Node(name, this); 
    this.children.push(child); 
    return child; 
}; 

//create a rootNode, having no parent 
rootNode = new Node('AAA'); 

//create node1 and add it to the child of rootNode 
node1 = rootNode.addChild('BBB'); 

//create node2 and add it to the child of rootNode 
node2 = rootNode.addChild('CCC'); 

//create node3 and add it to the child of node1 
node1.addChild('DDD'); 

//create node4 and add it to the child of node1 
node1.addChild('EEE'); 

//create node5 and add it to the child of node2 
node2.addChild('FFF'); 

function getTreeHTML(node, html) { 
    var i; 

    html = html || []; // In case they don't give it 

    if(node.level()==0) { 
     html.push('<ul>'); 
    } 

    html.push('<li>'); 
    html.push(node.name); 
    if (node.children.length > 0) { 
     html.push('<ul>'); 
     for (i = 0; i < node.children.length; ++i) { 
      getTreeHTML(node.children[i], html); 
     } 
     html.push('</ul>'); 
    } 
    html.push('</li>'); 

    if (node.level() == 0) { 
     html.push('</ul>'); 
    } 

    return html; 
} 

var treeHTML = getTreeHTML(rootNode).join(''); 
document.getElementById('content').innerHTML=treeHTML; 
+2

Oder entferne den 'html'-Parameter komplett, konstruiere das html in eine lokale Variable und gib das zurück. Es wäre etwas "sauberer". – Andreas

+1

Zu einem anderen Thema sollte der Code nicht html sein + = getTreeHTML (i, ''); und nicht html + = getTreeHTML (node.childs [i], ''); Ich meine, jeder ich werde ein Knoten-Typ selbst sein, also warum verwenden wir i als Index. Ich bin hier etwas verwirrt. –

+2

@Gunner: Nein, der Code ist richtig. 'for..in' durchläuft die Array-Einträge nicht, es durchläuft die Eigenschaft * name * (in diesem Fall Array * indexes *) des Objekts. Also wird "i" "0", dann "1" usw. –

1

Entfernen Sie den html Parameter alle zusammen:

function getTreeHTML(node){ 
    var html = ""; 
    if(node.level()==0) 
     html+='<ul>'; 

    html+='<li>'; 
    html+=node.name; 
    if(node.childs.length > 0){ 
     html+='<ul>'; 
     for(var i in node.childs){ 
      html+=getTreeHTML(node.childs[i]); 
     } 
     html+='</ul>'; 
    } 
    html+='</li>'; 

    if(node.level()==0) 
     html+='</ul>'; 
    return html; 
} 
+0

Es gibt einen logischen Fehler in meinem Gehirn. Danke für deine Antwort, es ist eine nützliche Antwort. – bobo

+1

Ich würde es beibehalten, aber es zu einem Array machen, so dass Sie die Möglichkeit haben, alles in einem Array aufzubauen und dann am Ende einen 'Join ('')' zu machen, der auf fast jedem (möglicherweise jedem) schneller ist. JavaScript-Implementierung, in die ich hineingeraten bin, als String-Verkettung. FWIW. –

+1

@ T.J in der Tat, ich würde auch das ganze Ding in Factory Design-Muster konvertieren und GetTreeHtml eine Funktion des Node-Objekts machen;) – Psytronic

Verwandte Themen