Tree 由JsonRestStore和jsonp支持的延迟加载dojo树

Tree 由JsonRestStore和jsonp支持的延迟加载dojo树,tree,dojo,lazy-loading,jsonp,deferred,Tree,Dojo,Lazy Loading,Jsonp,Deferred,我正在尝试使用Dojo工具包实现一个跨域、延迟加载树。到目前为止,我已经正确显示了顶级节点,但单击expando时,我得到了一个“延迟已解决”错误,我不知道为什么。通过查看firebug网络选项卡,我可以看到fetch方法似乎正在工作。我认为我的问题在我的_processResults方法中,可能与其中的_loadObject的定义有关 我觉得我应该更了解Dojo,因为我花了很多时间试图理解它。但是,唉,它真是一只野兽。。。我在其中一个sitepen博客()中看到一些关于JSONP和懒散加载不起

我正在尝试使用Dojo工具包实现一个跨域、延迟加载树。到目前为止,我已经正确显示了顶级节点,但单击expando时,我得到了一个“延迟已解决”错误,我不知道为什么。通过查看firebug网络选项卡,我可以看到fetch方法似乎正在工作。我认为我的问题在我的_processResults方法中,可能与其中的_loadObject的定义有关

我觉得我应该更了解Dojo,因为我花了很多时间试图理解它。但是,唉,它真是一只野兽。。。我在其中一个sitepen博客()中看到一些关于JSONP和懒散加载不起作用的内容,但没有提到除了JSONP是asyncronus之外为什么不可能。如果Dojo只是将传入的json数据塞进存储中,我不明白这有什么关系

也许这与我对数据的格式化有关-sitepen()上的另一个例子是使用jsonreststore在展开节点之前不会加载项,而我的格式在展开节点之前不会加载项,但在展开节点之前不会加载子节点

不用多说,这里是ta codez

<script type="text/javascript">
dojoConfig = {
parseOnLoad: true,
isDebug: true,
usePlainJson: true  
};
</script>
<script type="text/javascript" src="scripts/dojo_16/dojo/dojo.js"></script>

<script type="text/javascript">
    dojo.require("dojo.parser");
    dojo.require("dojo.io.script");
    dojo.require("dojox.rpc.Service");
    dojo.require("dojox.data.ServiceStore");                    
    dojo.require("dijit.tree.ForestStoreModel");                    
    dojo.require("dijit.Tree");         

    dojo.addOnLoad(function(){

        var mySmd = {
                "SMDVersion": "2.0",
                "id": "http://urlbehindfirewall/testtree/", 
                "description": "This is the service to get to the finder app backend data",

                transport: "JSONP",
                envelope: "URL",
                additionalParameters: true,
                target: "http://urlbehindfirewall/testtree/",               

                services: {
                    "getChildrenNodes": {
                    "target": "getChildrenNodes.php",
                        parameters: [
                            { name: "nodeId", type: "integer"}                             
                        ]
                    }
                }

        };

        var myService = new dojox.rpc.Service(mySmd);

        var myStoreParams = {               
            service : myService.getChildrenNodes,
            idAttribute : "Node_Id",
            labelAttribute : "Display_Name",
            _processResults: function(results, def){                                        
                var _thisStore = this;
                for(i in results){
                    results[i]._loadObject = function(callback){
                        _thisStore.fetch({
                        query: { nodeId: this.Node_Id },
                        onItem: callback
                        });
                    delete this._loadObject;
                    };
                }                   
                return {totalCount: results.length, items: results};                                                
            }
        };


        var myStore = new dojox.data.ServiceStore(myStoreParams);

        //create forestTreeModel
        var treeModelParams = {
            store: myStore,
            deferItemLoadingUntilExpand: true,
            childrenAttrs: ["Children_Nodes"],              
            rootId : 1,
            query: 1
            };

        var treeModel = new dijit.tree.ForestStoreModel(treeModelParams);

        var myTree = new dijit.Tree({
            model: treeModel,
            id: "myTree",
            showRoot: false 
            });

        dojo.byId("treeContainer").appendChild(myTree.domNode);
        myTree.startup();                   
    });

</script>
展开上述任何一个节点都将得到该节点的子节点,因此2将得到5,6,7,8的节点数组。(对于当前实现,可能不需要有子节点ID和子节点,但不应该破坏任何内容否?)

所以,我确信现在眼睛都睁大了,重申一下这个问题——是什么造成了这个“推迟已经解决”的错误?使用JSONP可以在树中进行延迟加载吗?不同的json结构会解决我的延迟加载问题吗?是否可以在dojo中重新格式化数据以使其正常工作?(我认为这就是_processResults方法…)是否有任何可公开访问的树数据服务可供实践


谢谢大家

经过大量的实验和挫折,我的发现如下:

是的,可以使用JSONP延迟加载树。是的,将数据转换成不同的格式有助于解决延迟加载问题。我在路上发现了一些绊脚石,我将在后面提到

下面是工作实现的代码。首先是服务:

invokeService.php

$callback = $_GET["callback"];
$nodeName = $_GET["node"];
$fileName = "pretendServiceJson/".$nodeName.".js";

print($callback . "(" . file_get_contents($fileName) . ")" );

?>
json/0.js-这是初始数据加载说明它是一个数组

[
{
   "Node_Id":"0",
   "Display_Name":"",
   "Children":[
      {
         "Node_Id":"1",
         "Display_Name":"node 1",
         "Obi_Id":"02",
         "Secondary_Names":"Blah blah secondary name node 1"
      },
      {
         "Node_Id":"2",
         "Display_Name":"node 2",
         "Obi_Id":"o2",
         "Secondary_Names":"Blah blah secondary name node 2"
      },
      {
         "$ref":"3",
         "Display_Name":"node 3",
         "Obi_Id":"o3",
         "Secondary_Names":"Blah blah secondary name node 3",
         "Children":true
      },
      {
         "Node_Id":"4",
         "Display_Name":"node 4",
         "Obi_Id":"o4",
         "Secondary_Names":"Blah blah secondary name node 4"
      },
      {
         "Node_Id":"5",
         "Display_Name":"node 5",
         "Obi_Id":"o5",
         "Secondary_Names":"Blah blah secondary name node 5"
      }
   ]
}
]
{
    "Node_Id": "3",
    "Display_Name": "node 3",
    "Obi_Id": "o3",
    "Secondary_Names": "Blah blah secondary name node 3",
    "Children": [
        {
            "$ref": "6",
            "Display_Name": "node 6",
            "Obi_Id": "o6",
            "Secondary_Names": "Blah blah secondary name 06",
            "Children":true
        },
        {
            "Node_Id": "7",
            "Display_Name": "node 7",
            "Obi_Id": "o7",
            "Secondary_Names": "Blah blah secondary name 07"
        }
    ]
}
假装服务JSON/3.js-这将是第一个延迟加载的项目-注意它是一个对象

[
{
   "Node_Id":"0",
   "Display_Name":"",
   "Children":[
      {
         "Node_Id":"1",
         "Display_Name":"node 1",
         "Obi_Id":"02",
         "Secondary_Names":"Blah blah secondary name node 1"
      },
      {
         "Node_Id":"2",
         "Display_Name":"node 2",
         "Obi_Id":"o2",
         "Secondary_Names":"Blah blah secondary name node 2"
      },
      {
         "$ref":"3",
         "Display_Name":"node 3",
         "Obi_Id":"o3",
         "Secondary_Names":"Blah blah secondary name node 3",
         "Children":true
      },
      {
         "Node_Id":"4",
         "Display_Name":"node 4",
         "Obi_Id":"o4",
         "Secondary_Names":"Blah blah secondary name node 4"
      },
      {
         "Node_Id":"5",
         "Display_Name":"node 5",
         "Obi_Id":"o5",
         "Secondary_Names":"Blah blah secondary name node 5"
      }
   ]
}
]
{
    "Node_Id": "3",
    "Display_Name": "node 3",
    "Obi_Id": "o3",
    "Secondary_Names": "Blah blah secondary name node 3",
    "Children": [
        {
            "$ref": "6",
            "Display_Name": "node 6",
            "Obi_Id": "o6",
            "Secondary_Names": "Blah blah secondary name 06",
            "Children":true
        },
        {
            "Node_Id": "7",
            "Display_Name": "node 7",
            "Obi_Id": "o7",
            "Secondary_Names": "Blah blah secondary name 07"
        }
    ]
}
还有另一个json文件6.js,但我想你明白了。最后是魔法

            dojo.require("dojo.parser");
        dojo.require("dojo.io.script");
        dojo.require("dojox.rpc.Service");
        dojo.require("dojox.data.JsonRestStore");                   
        dojo.require("dijit.tree.ForestStoreModel");                    
        dojo.require("dijit.Tree");         

        dojo.addOnLoad(function(){

            var mySmd = {
                    "SMDVersion": "2.0",
                    "id": "http://localhost/pretendService.php", 
                    "description": "This is the service to get to the finder app backend data",

                    transport: "JSONP",
                    envelope: "URL",
                    additionalParameters: true,
                    target: "http://localhost/",                

                    services: {
                        "getNode": {
                        "target": "pretendService.php",
                            parameters: [
                                { name: "node", type: "string"}                            
                            ]
                        }
                    }
            };

            var myService = new dojox.rpc.Service(mySmd);                       

            var myStore = new dojox.data.JsonRestStore({                
                service : myService.getNode,
                idAttribute : "Node_Id",
                labelAttribute : "Display_Name"             
            });     

            //create forestTreeModel
            var treeModelParams = {
                store: myStore,
                deferItemLoadingUntilExpand: true,
                childrenAttrs: ["Children"],                
                //rootId : "0",
                query: "0"
                };

            var treeModel = new dijit.tree.ForestStoreModel(treeModelParams);

            var myTree = new dijit.Tree({
                model: treeModel,
                id: "myTree",
                showRoot: false,
                persist: false
                });

            dojo.byId("treeContainer").appendChild(myTree.domNode);
            myTree.startup();

        });

    </script>
</head>

<body class="tundra">

<div id="treeContainer"></div>

</body>
</html>
dojo.require(“dojo.parser”);
require(“dojo.io.script”);
require(“dojox.rpc.Service”);
require(“dojox.data.JsonRestStore”);
require(“dijit.tree.ForestStoreModel”);
dojo.require(“dijit.Tree”);
dojo.addOnLoad(函数(){
var mySmd={
“SMDVersion”:“2.0”,
“id”:”http://localhost/pretendService.php", 
“说明”:“这是获取finder应用程序后端数据的服务”,
传输:“JSONP”,
信封:“URL”,
其他参数:true,
目标:“http://localhost/",                
服务:{
“getNode”:{
“target”:“invokeService.php”,
参数:[
{名称:“节点”,类型:“字符串”}
]
}
}
};
var myService=newdojox.rpc.Service(mySmd);
var myStore=new dojox.data.JsonRestStore({
服务:myService.getNode,
idAttribute:“节点\u Id”,
labelAttribute:“显示名称”
});     
//创建forestTreeModel
变量treeModelParams={
商店:myStore,
DeliveItemLoadingUntilexPand:true,
childrenAttrs:[“Children”],
//rootId:“0”,
查询:“0”
};
var treeModel=新的dijit.tree.ForestStoreModel(treeModelParams);
var myTree=新的dijit.Tree({
型号:treeModel,
id:“myTree”,
showRoot:错,
坚持:错
});
byId(“treeContainer”).appendChild(myTree.domNode);
myTree.startup();
});
这里最大的教训是,有两种不同的方法(尽我所能做到最好)将数据放入存储,然后再放入树中。第一个数据加载将来自一个fetch,它需要一个项目数组。随后的延迟加载项(假设您正确设置了服务并得到了响应)将经过loadItem,并且该方法将需要一个对象

如果您将初始加载数据作为一个对象输入,您将不会在页面上看到任何树,尽管在firebug中看到了响应。但是没有错误

如果将延迟加载的数据作为数组输入,则会得到一个“TypeError:args.item未定义”-似乎loadItem第二次被调用为2x,而不是结果对象,它是一个空对象

如果在创建存储时定义了rootId,它将不会显示树,并给您一个“无法在指定层次插入节点”错误

以上所有错误都是使用JsonRestStore发现的。文档中说JsonRestStore继承了read函数