1

だから私はこのようなJSONをいくつか持っています(プライバシー上の理由からキー/値が変更されました)。これは基本的に、オブジェクトの「子」配列を持つオブジェクトであり、各要素はオブジェクトの独自の「子」配列などを持ちます。

{
"name": "Main Area",
"children": [
    {
        "name": "Sub-section A",
        "children": [
            {
                "name": "Procedure 1"
                "children": [
                    {
                        "name": "Sub-procedure A",
                        "children": null
                    },
                    {
                        "name": "Sub-procedure A",
                        "children": null
                    },
                    {
                        "name": "Sub-procedure A",
                        "children": null
                    }
                ]
            },
            {
                "name": "Procedure 2"
                "children": [
                    {
                        "name": "Sub-procedure A",
                        "children": null
                    },
                    {
                        "name": "Sub-procedure A",
                        "children": null
                    },
                    {
                        "name": "Sub-procedure A",
                        "children": null
                    }
                ]
            },
            {
                "name": "Procedure 3"
                "children": [
                    {
                        "name": "Sub-procedure A",
                        "children": null
                    },
                    {
                        "name": "Sub-procedure A",
                        "children": null
                    },
                    {
                        "name": "Sub-procedure A",
                        "children": null
                    }
                ]
            },
        ]
    }
]
}

...そして、私が進むにつれて、それが数倍大きく/深くなる可能性があります。ここでの目標は、このデータを (折りたたみ可能な) ツリー図に変換し、knockout.js (できれば) を使用して HTML ページに表示することです。ただし、すべてのロジックは JavaScript コードである必要があります (JSON を jQuery AJAX で取得し、何らかの方法で処理し、表示します)。

このように 90 度回転しただけで、横ではなく下になります。 http://www.education.vic.gov.au/images/content/studentlearning/mathscontinuum/icecream.gif

jsTree のようなライブラリがあることはわかっていますが、要点は、これも学習体験にしたいので、ここで独自のコードを作成したいと考えています。また、jsTree はその構造をディレクトリ ツリーのように表示します。私が探しているのは、ページの幅全体を埋める、より視覚的なトップダウン ツリー図です。

問題は、私が立ち往生しているということです。これらすべてのネストされた配列/オブジェクトに頭を包むことはできません。おそらく、配列全体を再帰的に反復するいくつかの異なる関数を作成して、約 3 時間かけて試してみましたが、正しく動作させることはできません。

私の頭をよぎった最新のアイデアは、最も深い要素から始めて上に移動し、何らかの方法でステップをツリー図のレベルに変換し、最上部に到達するまで、JSON 構造を調べて、その時点で終了するというものでした。

それで、私を正しい方向に向けてもよろしいですか?私のために何十行ものコードを書く必要はありません。私がこれをどこに持っていくべきか、おそらくいくつかの疑似コードを教えてください。

前もって感謝します!

アップデート

もう少し先に来ました。今後の参考のためにコードを共有したいと思いました。これで、ノード オブジェクトの配列と基本的な ul/li 構造が作成されました (後で、ノックアウト .js を投げることができます)。まだ CSS/JS の部分を理解する必要がありますが、それは私が進むにつれて来るでしょう。

注目すべき点は、JSON 構造のすべての「null」値を「[]」に変更したことです。これは、このコンテキストで使用する方が便利です。

//node class
function node(label, children, node_id, parent_id) {
    this.label = label;
    this.children = children;
    this.node_id = node_id;
    this.parent_id = parent_id;
}

//tree class
function tree(root) {
    var self = this;
    self.root = root;
    if(!$.isArray(self.root.children)) {
        return;
    }
    self.nodeCount = 0;
    self.nodes = []; //This will be the main node array

    //Adds nodes to the array, recursive
    self.addNode = function(_node) {
        self.nodeCount++;
        self.nodes.push(_node);
        //Check if the branch ends here
        if(_node.children.length < 1) {
            return;
        }
        var tmpParent = _node;
        //Add children
        for(var i = 0; i < _node.children.length; i++) {
            self.addNode(new node(_node.children[i].name, _node.children[i].children, self.nodeCount, tmpParent.node_id));
        }
    }

    self.draw = function() {
        //Populate nodes array
        self.rootNode = new node(self.root.name, self.root.children, 0, -1);
        self.addNode(self.rootNode); //Kicks off the recursion
        //Create the first/"root" node
        $(".tree-wrapper").append('<ul id="0"><li class="title">'+ self.rootNode.label +'</li></ul>');
        //Create nodes and populate them with children
        for(var i = 0; i < self.nodes.length; i++) {
            //Check if the node has children
            if(self.nodes[i].children.length > 0) {
                //Wrap a new <ul> in a <li>, add a title <li> to the created <ul>
                $("#"+ self.nodes[i].parent_id).append('<li><ul id="'+ self.nodes[i].node_id +'"><li class="title">'+ self.nodes[i].label +'</li></ul></li>');
            } else {
                //Simply append a <li> with a label to the parent <ul>
                $("#"+ self.nodes[i].parent_id).append('<li id="'+ self.nodes[i].node_id +'">'+ self.nodes[i].label +'</li>');
            }
        }
    }
}

答えてくれたみんなありがとう!ヒント/ヒントがある場合は、躊躇しないでください;)私のコードは、おそらく何らかの方法で短縮/最適化される可能性があります!

4

3 に答える 3

1

私は最近、ノックアウトを使用してまったく同じことを実装しましたが、キャンバスではなく DOM 要素でレンダリングしました。

私がそれをした方法:

<script ko template = "node">
    <div class="node">
        <a href="#" data-bind="click: toggleChildren()">Open children</a>
        <div class="children" data-bind="visible: childrenOpen, foreach: children, template: node"> 
        </div>   
    </div>
</script ko template>

<div class="nodes" data-bind="foreach: children, template: node">
</div>

ViewModel 側:

function MyVM() {
    this.nodes = ko.observable([]); // this is a list of Node objects. each Node object has a list of children, that are also Node objects
}

ko.applyBindings(new MyVM());

モデル側:

function Node(name, etc.) {
    var self = this;

    this.childrenOpen = ko.observable(false);
    this.children = ko.observable([]);

    this.toggleChildren = function() {
        self.childrenOpen(!self.childrenOpen());
    }
}

あとは、次のことだけです。1) ViewModel にノードを設定します。2) ツリーのように見えるように CSS を記述します。

実際にはネストされた順序なしリスト (< ul >< li >) を使用しましたが、それは問題ではありません。

今、これはちょうど表示されています。双方向性が必要な場合は、おそらくいくつかのツリー ウォーキング アルゴリズムを実装し、子の親ノードへの参照を保持する必要があります (これは非常に役立ちます)。

于 2013-08-23T07:00:40.533 に答える
0

申し訳ありませんが、PHP以外の言語についてはあまり知りません。PHPで使用します

// first degree
foreach ($result->children as $arr) { 
// Where $result is data i got from json_decode(fetch_data())
  echo $arr->name; // Sub-section A

     // second degree
     foreach ($arr->children as $arr2) {
        echo $arr2->name; //Procedure 1, Procedure 2 , ...
     }
}

私の主張を理解して、あなたの Java に適用していただければ幸いです。

于 2013-08-23T01:11:57.283 に答える