跳转到主要内容

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

当您初次登录到 developerWorks 时,将会为您创建一份概要信息。您在 developerWorks 概要信息中选择公开的信息将公开显示给其他人,但您可以随时修改这些信息的显示状态。您的姓名(除非选择隐藏)和昵称将和您在 developerWorks 发布的内容一同显示。

所有提交的信息确保安全。

  • 关闭 [x]

当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

所有提交的信息确保安全。

  • 关闭 [x]

使用 JsonRestStore 延迟加载 Dojo 树上的子节点

高效地获取和显示大量数据集

Ina Arya, 资深软件工程师, IBM
http://www.ibm.com/developerworks/i/p-iarya.jpg
Ina 是 IBM India Software Lab 的 Software Development Workbench 的系统软件工程师。她有四年多软件开发经验,包括运用 Java 技术的 Web 应用程序。

简介: 学习如何使用 Dojo 和 JsonRestStore 创建一个延迟加载子节点的 Dojo 树。通过使用 JsonRestStore 上定义的方法控制数据存储来删除,添加和更新节点,使用 Dojo 树上的延迟加载功能,高效地获取和显示大量数据集。

发布日期: 2011 年 12 月 05 日
级别: 中级 原创语言: 英文
访问情况 : 1177 次浏览
评论: 


简介

,过去用于在父-子关系中导航分层数据,能够帮助您轻松地理解长的数据和数据关系清单。Dojo 支持创建树,并且 Dojo 中的树遵从 Model-View-Controller(MVC)设计模式。在数字的树中,角色由以下的组件扮演:

控制器(dojox.data 存储)
该存储负责存储所有非关系型数据库格式的数据。
模型(dijit.tree ForestStoreModel/TreeStoreModel)
根据用户选择的模型,格式化存储在层次顺序中的数据。
视图(dijit.Tree)
显示由模型对象创建的数据的树。

使用 Dojo 树中的 MVC,树的创建由控制器开始,然后是模型,最后是视图,如图 1 所示。


图 1. 遵从 MVC 设计模型的 Dojo 树
显示由底层的控制器层,到模型层,然后到顶层的视图层的金字塔。

您可以使用各种 Dojo 数据存储在 Dojo 中创建树。在本文中,学习使用基于 REST API 的 Dojo 存储 JsonRestStore 创建一个延迟加载的 Dojo 树。

延迟加载

延迟加载是一种仅在需要时,从用户数据库获取数据的技术。服务器只获取那些由用户展开的节点,这可以优化树的性能。树的延迟加载根据树中存储的数据量,可能导致廉价的,或者昂贵的操作。

在少量的数据上应用延迟加载会导致对服务器的多次请求,而缓慢的响应可能会导致用户的沮丧。但是,在一个有大量数据集的生产环境中,延迟加载往往为您提供优势。

在深入了解 Dojo 树创建过程之前,下一部分包含了一些创建延迟加载树的关键概念。


Dojo 树的创建

一个 Dojo 树中有几个重要的构建模块:

  • JsonRestStore 引用功能
  • deferItemLoadingUntilExpand
  • JSON 数据

JsonRestStore 引用功能

JSON 引用是由 JsonRestStore 提供的属性,您使用它从一个对象获取另一个对象的引用(无需包括真实的对象)。从一个对象引用另一个是由 JsonRestStore$ref 属性提供的。

父-子关系可以在运行时,使用父级中 $ref 属性的值解决,这个值还是子节点的 id 值。父节点的 JSON 对象可能类似以下例子。

{ 
      "id": "node1",
      "name": "Subjects",
        $ref: "child1"
}

子级 JSON 对象类似以下例子。

{ 
      "id": "child1",
      "name": "Math",
        $ref: "author1"
}
            

在第一段代码例子中,父节点有一个 "child1"$ref 属性值,这就意味着它引用子节点的 id 值。这个值可以在父节点被展开时才进行解析(本文稍后显示)。

在第二段代码例子中,id “child1” 要完全匹配父级 $ref 值。您可以使层次结构继续,类似第二个例子中的 $ref:"author1"

deferItemLoadingUntilExpand 属性

Dojo Toolkit 1.4 推出了一个新属性,deferItemLoadingUntilExpand,用于 Dojo 树模型。Dojo Toolkit 的较早版本缺少此功能,当任意子节点被扩展时,所有树节点都被重新获取,并加载到 Dojo 数据库。但是,使用 deferItemLoadingUntilExpand 属性,如果 deferItemLoadingUntilExpand 被设置为 true,它就只能获取被请求节点的子级,并在数据存储中进行更新。这会帮助增加延迟加载树的效率。

Dojo 树的 JSON 数据

JsonRestStore 有一个 JSON 格式数据的预定义模式。在开始创建树之前,您需要具备对 JSON 的基本理解。本文使用树的 JSONObjectJSONArrayJsonString,所以例子可以获得正确格式的数据。本文中的例子从 Java™ 类中获取 JSON 数据,并且需要 JSON 数据作为由 JsonRestStore 处理的返回字符串。


创建一个延迟加载的 Dojo 树

在这一部分,您可以使用 JsonRestStore 创建一个延迟加载的树。例子中创建了一个小说书店的树。这个树中将会包含书籍和作者的信息,书籍和作者之间有分层结构。您可以使用延迟加载的 Dojo 树创建这个分层结构,使应用程序更高效。

Dojo 树使用 MVC 模型,这个模型有两个形式:TreeStoreModelForestStoreModel。例子使用 ForestStoreModel 来构建一个树。首先,您需要声明和定义应用程序的 JsonRestStore。使用 REST 服务创建一个 JsonRestStore,或者直接映射一个 URL 到目标参数。

例子声明了一个服务,它将基于 Dojo 的 Asynchronous JavaScript 和 XML(Ajax)调用放置到一个负责从数据库获取数据,并返回 JSON 格式字符串的 Java 类中。从 Java 类检索后,数据更新为服务参数。

从生成客户端代码入手,如清单 1 中所示的 JsonRestStoreTree.jsp 代码。


清单 1. 创建 REST 服务和 JsonRestStore
				
var booksService = function(query, queryOptions) 
{	

return dojo.xhrGet({url:" 
/BookStoreTree/com/tree/actions/JsonRestStoreTreeAction.action", 
handleAs:'json',content:{query:query, queryOptions:queryOptions}});

};

var booksDataStore = new 
dojox.data.JsonRestStore({target:'booksData',service: booksService,
labelAttribute:"name"});
            

或者,可以通过制定存储目标直接创建存储,如清单 2。


清单 2. 使用目标参数创建存储
				
var booksDataStore = new dojox.data.JsonRestStore({target: 
"/BookStoreTree/com/tree/actions/JsonRestStoreTreeAction.action ",
labelAttribute:"name"});
            

现在已经创建了存储,那您就需要使用 ForestStoreModel 创建一个模型。例子中编程创建了一个模型,如清单 3。代码将 deferItemLoadingUntilExpand 值设置为 true


清单 3. 创建模型
				
var treeModel = new dijit.tree.ForestStoreModel({
                     store: booksDataStore,
                     deferItemLoadingUntilExpand: true,
                     rootLabel: "Subjects",
                     childrenAttrs: ["children"]
       	     });
            

存储和模型已经完成,现在继续创建 Dojo,如清单 4。


清单 4. 创建 Dojo 树
				
<div dojoType="dijit.Tree" model="booksDataStore " 	
     persist="false" id="booksDataTree">
            

与创建树的客户端代码一样,开始编写 Java 代码来获得 JSON 格式的书籍的初始数据。

清单 5 中的代码返回了数据的 JSON 格式。数据稍后存储在 booksDataStore


清单 5. 获取初始树数据的 Java 代码
				
public String getSubjectList() throws IOException 
	{
		//Code to query subjects list from DB
		//call DB-side function to get the books object
		Map<String,String> booksNameMap = new
                               HashMap<String, String>();
		//ex. Map booksNameMap =
                server.GetListOfSubjects();
		//above code is specific to application
		JSONObject subObj = new JSONObject();
		JSONArray subArray = new JSONArray();
		
		for(int i=0; i< booksNameMap.size(); i ++)
		{
                      String subjectName = booksNameMap.get(i);

                      subObj.put("id", subjectName +"Id");
                      subObj.put("name", subjectName);
                      subObj.put("$ref","author"+ i);
                      subObj.put("children", true);
		}

		subArray.add(subObj);	
		jsonString = subArray.serialize(true);
		setJsonString(jsonString);
		return jsonString;
	}
            

清单 5 中的代码在 JSONArray 中存储数据,这是加载树的初始数据所需要的。创建的树如图 2 所示。


图 2. 初始 Dojo 树
目录结构,书名作为主目录,算法,c 编程,数据结构,java 编程作为子目录。

现在已经创建了树,您可以扩展获取被请求节点数据的节点了。您将会看到引用属性在扩展任意节点时起到多么重要的作用。

清单 6 中,扩展 id "subjectNameId" 父级节点时,就会进行 getListOfAuthors() 方法调用。因为 "subjectNameId "$ref 属性被设置为 "author1",author1 的节点数据被返回,而且自动更新为树的子节点。


清单 6. 获取子节点数据
				
public String getListOfAuthors() throws IOException
	{
		//Code to query authors list from DB
		//call DB-side function to instantiate 				
                authorsNameMap object
		Map<String,String> authorsNameMap = new
                               HashMap<String, String>();
		//ex. Map authorsNameMap = 						
                server.GetListOfAuthors();
		//above code is specific to application
		JSONObject authObj = new JSONObject();
		
		for(int i=0; i< authorsNameMap.size(); i ++)
		{
                      authObj.put("id", "author"+i);
                      authObj.put("name",
                                authorsNameMap.get(i));
		}
	
		jsonString = authObj.serialize(true);
		setJsonString(jsonString);
		return jsonString;
	}

尽管父级数据以 JSONArray 格式,而例子中以 JSONObject 格式发送子节点数据。这非常重要,因为子数据是以 JSONObject 格式被捕获。

已创建的树如图 3 所示。当 C Programming 节点被扩展时,就会有请求发送给服务器,只获取这个节点的数据。


图 3. 延迟加载的 Dojo 树
目录结构,书名作为主目录,算法,c 编程(旁边有计时器),数据结构,java 编程作为子目录。

从树中删除一个节点

在删除,添加,或者更新节点时,您不更新树视图。反而,您需要更新连接到数据存储的树模型。最重要的是,如果想要修改树,您需要更新数据存储。

在书店的例子中,存储数据包含各种书籍的信息,每本书都由 "id" 值惟一地识别。您可以使用 "id" 值获取节点,并从存储中删除节点。清单 7 显示了从树中删除节点的代码段。


清单 7. 从 Dojo 树中删除节点
				
function deleteNodeFromTree()
	{
		//delete from the bookstore//
		booksDataStore.fetchItemByIdentity({
				identity: 'AlgorithmsId',
				onItem: dojo.hitch(booksDataStore,
                                          function(item) {
				booksDataStore.deleteItem(item);
				booksDataStore.save({
                                     onComplete: function() {
                                          alert("Save Complete");
								}
							});
						})
					});
}

清单 7 中的代码通过节点的标识(在该例子中为 'AlgorithmsId')从存储中获取节点。获取所需节点后,调用 JsonRestStoredeleteItem() 方法,这可以从数据存储中删除 'AlgorithmsId' 数据。删除节点后,Dojo 树如图 4 所示。


图 4. 算法节点被删除
目录结构,书名作为主目录,c 编程,数据结构,java 编程作为子目录。

在树中添加一个节点

JsonRestStorenewItem(item, {parent : parentItem, attribute : children}) 功能,用于在存储中添加新项目,您还可以使用它添加一个新节点到树中。该方法的调用类似例子中删除节点时的 deleteItem() 调用。在书店中,添加 "A.K.Das" 作为 Data Structures 节点的子级。


清单 8. 在 Dojo 树中添加节点
				
function addNodeToTree()
{
	//add data to the bookstore//
	booksDataStore.fetchItemByIdentity({
				identity: 'AlgorithmsId',
				onItem: dojo.hitch(booksDataStore,
                                                function(item) {
				booksDataStore.newItem(
                                          name: 'A.K.Das',
                                          ref: $'AlgorithmsId',
                                               item);
				booksDataStore.save({
				onComplete: function() {
                                          alert("Add node
                                  Complete");
								}
								});
							})
						});
}

清单 8 中的代码获取您想要添加新子级的项目。或者,换句话来说,新节点成为您正在从存储中获取的节点的子节点。父节点是 'AlgorithmsId',即书名,例子中添加一个 'A.K.Das' 作为作者。图 5 显示了添加新节点之后的树。


图 5. 子节点被添加到 Algorithms 节点
目录结构,书名作为主目录,算法,c 编程,数据结构,java 编程作为子目录,A.K. Das 显示在算法下面。

更新树的节点

要更新树的节点,您需要更新位于数据存储的数据。再一次,例子调用数据存储的 fetchItemByIdentity 方法,使用 JsonRestStoresetValue(item, attribute, value) 方法来更新目标节点的数据。

清单 9 显示了代码,其中在 booksDataStore 上调用了 setValue(item, attribute, value) 方法,'name' 属性的值变更为所选节点。


清单 9. 更新 Dojo 树的节点
				
function updateNodeToTree()
{
	//update data of the bookstore//
	booksDataStore.fetchItemByIdentity({
				identity: 'AlgorithmsId',
				onItem: dojo.hitch(booksDataStore,
                                                function(item) {
				booksDataStore.setValue(item, 'name',
                                                    'Discrete');
				booksDataStore.save({
				onComplete: function() {
                                          alert("Update Complete");
								}
								});
							})
            

JsonDataStoresetValue(item, attribute, value) 方法更新了当前节点。清单 9 中的代码将 'AlgorithmsId' 节点的名称由 Algorithms 更新到 Discrete。图 6 显示了更新后的树。


图 6. 节点 Algorithms 更新到 Discrete
目录结构,书名作为主目录,c 编程,数据结构,离散和 java 编程作为子目录。

结束语

总而言之,基于 Dojo 和 REST 的 JsonRestStore 为允许高效地获取和显示大量数据集的延迟加载树提供了良好支持。当您使用 JsonRestStore 提供的方法时,就能够轻松地更新、添加和删除 Dojo 树。Dojo 和 JsonRestStore 让您能够利用 Dojo 树上的延迟加载功能。您可以通过将 Dojo 树部件和基于 REST 数据存储完美结合,创建高级的,基于丰富文本的 UIs。


参考资料

学习

  • 阅读更多关于 Dojo dijit.Tree 的资料,了解树如何帮助解决长的、分层的清单。

  • 了解更多关于 JsonRestStore 的功能和使用。

  • 探索 Dojo API for JsonRestStore。JsonRestStore 使用 Rest 命令(PUTPOST,或者 DELETE)会使所有已保存的修改被发送到服务器。

  • Efficient Lazy Loading of a Tree” 提供了使用 JsonRestStore 构建一个延迟加载的树的例子。

  • 了解更多关于 JSON 的信息,它是便于人类读写的轻量级数据交换格式。

  • developerWorks Web development 专区:通过专门关于 Web 技术的文章和教程,扩展您在网站开发方面的技能。

  • developerWorks Ajax 资源中心:这是有关 Ajax 编程模型信息的一站式中心,包括很多文档、教程、论坛、blog、wiki 和新闻。任何 Ajax 的新信息都能在这里找到。

  • developerWorks Web 2.0 资源中心,这是有关 Web 2.0 相关信息的一站式中心,包括大量 Web 2.0 技术文章、教程、下载和相关技术资源。您还可以通过 Web 2.0 新手入门 栏目,迅速了解 Web 2.0 的相关概念。

  • 查看 HTML5 专题,了解更多和 HTML5 相关的知识和动向。

获得产品和技术

讨论

关于作者

http://www.ibm.com/developerworks/i/p-iarya.jpg

Ina 是 IBM India Software Lab 的 Software Development Workbench 的系统软件工程师。她有四年多软件开发经验,包括运用 Java 技术的 Web 应用程序。

关于报告滥用的帮助

报告滥用

谢谢! 此内容已经标识给管理员注意。


关于报告滥用的帮助

报告滥用

报告滥用提交失败。 请稍后重试。


developerWorks:登录


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 使用条款

 


当您初次登录到 developerWorks 时,将会为您创建一份概要信息。您在 developerWorks 概要信息中选择公开的信息将公开显示给其他人,但您可以随时修改这些信息的显示状态。您的姓名(除非选择隐藏)和昵称将和您在 developerWorks 发布的内容一同显示。

请选择您的昵称:

当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

(长度在 3 至 31 个字符之间)


单击提交则表示您同意developerWorks 的条款和条件。 使用条款.

 


为本文评分

评论

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Web development
ArticleID=779879
ArticleTitle=使用 JsonRestStore 延迟加载 Dojo 树上的子节点
publish-date=12052011

标签

Help
使用 搜索 文本框在 My developerWorks 中查找包含该标签的所有内容。

使用 滑动条 调节标签的数量。

热门标签 显示了特定专区最受欢迎的标签(例如 Java technology,Linux,WebSphere)。

我的标签 显示了特定专区您标记的标签(例如 Java technology,Linux,WebSphere)。

使用搜索文本框在 My developerWorks 中查找包含该标签的所有内容。热门标签 显示了特定专区最受欢迎的标签(例如 Java technology,Linux,WebSphere)。我的标签 显示了特定专区您标记的标签(例如 Java technology,Linux,WebSphere)。