Dojo tree use experience

Thanks to reedseutozte’s contribution, an introduction to the use of dijit.Tree, a very good article, and it can also reflect the core design ideas of Dojo. As the most commonly used control, I believe this article can help many students. Thanks again to reedseutozte for bringing the first article to the Dojo Chinese blog:)


Overview

Dojo’s dijit.tree code structure completely follows MVC The structure is very rigorous:

M: model uses the dojo.data.itemFileReadStore (read-only) or dojo.data.itemFileWriteStore (read-write) provided by the dojo basic package. Tree does not directly use Store but uses the dijit.tree.TreeStoreModel class to concatenate the sotre and the structure required by the tree structure.

V: view is the dijit.tree and dijit_TreeNode defined in tree.js. This class mainly completes the front-end interface rendering and the management between node objects on the tree.

C: _dndSelector.js This file name began to confuse me, and later I found out that even if the drag-and-drop feature is not used, the code in this class will still be called. This class defines the selected node and deletes the node , Add node, drag node operation.

There are many sources of information about trees on the Internet, and dojo itself also provides a wealth of examples. Here are some usages that are not covered in the examples.

lazy load of trees
In fact, lazy loading itself does not have too many problems, but there are two points that need to be explained


Icon processing
Dojo will automatically judge the icons of leaf/non-leaf nodes. During lazy loading, because some nodes do not load child nodes, dojo will display the default leaf icons when processing the icons of these nodes, so here you need to re-implement the mayHaveChildren method of treemodel, the code is as follows

[javascript] view plain copy

  1. var treeModel=newdijit.tree.ForestMode({ span>
  2. … …
  3. });
  4. treeModel.mayHaveChildren = function(item) span>
  5. {
  6. //item is the data item of the corresponding node. The function returns true to indicate that the node is a non-leaf node, and dojo will attach a non-leaf icon to this node
  7. if(item.root)
  8. {
  9. returntrue;
  10. else
  11. //It is considered that when the tree is initialized There is a type attribute in the data item of each node, which is judged according to the attribute
  12. return(treeModel.store.getValue(item,‘type’) !=‘xxxx’)
  13. }


Node loading
The biggest feature of Dojo tree It is completely data-driven, so the loading of the node can be achieved by adding childran to the data item of the corresponding parent node, see the following code:

[javasc ript] view plaincopy

< /div>

  1. varoldExpand=dijit.Tree.prototype._onExpandoClick;
  2. dojo.extend( dijit.Tree, {
  3. _onExpandoClick:function(message)
  4. {
  5. varnode=message.node; li>
  6. reloadNode(node) ;
  7. oldExpand.apply(this, Arguments); < /li>
  8. });
  9. < span s tyle="margin:0px; padding:0px; border:none; color:black; background-color:inherit">functionreloadNode(node )
  10. {
  11. var store = node.tree.model.store;
  12. varnodeItem=node.item;
  13. //Suppose we obtain the child node data of the changed node from the background through this method
  14. vardataList=getChildList();
  15. dojo.forEach(dataList,function(x){
  16. /span>
  17. x.type=‘yyy’ ;
  18. //The above code can be seen and needs to be added. The function of the above line of code is to access the type attribute of the item corresponding to the node through the store.getValue method
  19. store.newItem(x,{ parent:nodeItem, attribute: ‘children’});
  20. ));
  21. }


add/delete/modify nodes
It has been said before that the dojo tree adopts the MVC mode, so the above operations can be achieved through the operation of the store
1 . Increase
The lazy loading code above has been listed and I will not repeat it here

2. Modify :
Suppose the treeNode object instance of the node to be modified is node

[javascript] view plain copy

  1. tree.model.store.setValue(node.item,‘name’/*取决于定义store时的label属性*/, newName)    


3. 删除
假设需要删除的节点的treeNode对象实例为node

[javascript]  view plain copy

  1. tree.model.store.deleteItem(node.item)    


鼠标函数
上面说了很多,可以发现所有操作都需要获取树节点对应的dojo对象才可以进行。那么这个对象如何获得呢?我们知道对树的操作分为两种,左键点击或者右键菜单,鼠标点中了相对应的节点就可继续往下操作,因此下面介绍如何通过鼠标事件获得节点对象

click

[javascript]  view plain copy

  1. tree.connect(tree, ‘onClick’, clickTreeNode);    
  2. function clickTreeNode(item/*点中节点对应的数据项*/, node/*点中的对象,这里node.item就是的第一个参数*/,evt/*事件*/)    
  3. {    
  4. …………….    
  5. }    

                        
rightClick
右击一般是打开菜单,这里的菜单也是dojo的,因此判断函数为

[javascript]  view plain copy

  1. dojo.connect(pMenu, ‘_openMyself’function(e){    
  2.     var node = dijit.getEnclosingWidget(e.target); /*node就是节点对象*/        
  3. });    


代码选中节点

[javascript]  view plain copy

  1. tree.dndController.setSelection([node])    


托拽控制
Dojo的树提供托拽功能,使用托拽功能需要在实例化tree的时候将tree的dndController属性定义为’dijit.tree.dndSource’ 。 betweenThreshold为0表示不允许同目录下拖动。

实际应用中我们要增加一些限制,这坐介绍两种

i)选中的对象是否允许拖拽

[javascript]  view plain copy

  1. dojo.connect(tree.dndController, ‘onMouseDown’function(e){    
  2.     //如果你的树上有滚动条,请加入如下代码,否则如果你选中了节点后拖动滚动条会出现节点拖拽精灵    
  3.     if (dijit.getEnclosingWidget(e.target) == tree)    
  4.     {    
  5.         tree.dndController.mousedown = false;    
  6.         return;            
  7.     }    
  8.     //tree.dndController.mousedown为true表示允许拖拽,反之就是不允许,e为鼠标事件对象    
  9.     //tree的selectedNodes属性可以返回选中的节点列表,这里的代码表示每个选中节点的数据项中的type属性都是xxx才能拖动    
  10.     tree.dndController.mousedown = dojo.every(tree.selectedNodes, function(node){    
  11.         return (tree.model.store.getValue(node.item, ‘type’) == ‘xxx’)    
  12.     });      
  13. });    


ii)判断目标节点是否接受正在拖拽的对象

[javascript]  view plain copy

  1. tree.checkItemAcceptance = function(target, source, position)    
  2. {    
  3. //target: DomNode 目标节点对应的dom, 用dijit.getEnclosingWidget(target)可以获得TreeNode对象    
  4. //source: dijit.tree.dndSource 被拖动的treeNode对象,是一个列表,因为tree允许一次拖动多个节点  < span style="margin:0px; padding:0px; border:none; background-color:inherit">  
  5. //position: ‘over’, ‘before’, ‘after’    
  6. //返回true表示允许drop    
  7. }    

[ja vascript]  view plain copy

  1. var treeModel = new dijit.tree.ForestMode({    
  2.     …….    
  3. });    
  4. treeModel.mayHaveChildren = function(item)    
  5. {    
  6.     //item为对应节点的数据项,该函数返回true表示该节点为非叶子节点,dojo就会为这个节点附着上非叶子图标    
  7.     if(item.root)    
  8.     {    
  9.          return true;    
  10.     }    
  11.     else    
  12.     {    
  13.         //这里认为初始化树的时候对于每一个节点的数据项中都有type属性,根据属性判断    
  14.         return (treeModel.store.getValue(item, ‘type’) != ‘xxxx’)    
  15.     }    
  16. }    

[javascript]  view plain copy

[javascript]  view plain copy

< strong>[javascript]  view plain copy

  1. var oldExpand = dijit.Tree.prototype._onExpandoClick;    
  2. dojo.extend(dijit.Tree, {    
  3.     _onExpandoClick: function(message)    
  4.     {    
  5.         var node = message.node;    
  6.         reloadNode(node);    
  7.         oldExpand.apply(this, arguments);    
  8.     }    
  9. });        
  10. function reloadNode(node)    
  11. {    
  12.     var store = node.tree.model.store;    
  13.     var nodeItem = node.item;    
  14.     //假设我们通过这个方法从后台取得了改node的子节点数据    
  15.     var dataList = getChildList();    
  16.     dojo.forEach(dataList, function(x){    
  17.         ……    
  18.         x.type = ‘yyy’;    
  19. < span style="margin:0px; padding:0px; border:none; color:black; background-color:inherit">        //以上的代码可以看需要添加,上面一行代码的作用是可以通过store.getValue方法访问该节点对应的item的type属性    
  20.         store.newItem(x,{parent:nodeItem, attribute: ‘children’});    
  21.     });    
  22. }    

[javascript]  view plain copy

[javascript]  view plain copy

[javascript]  view plain copy

  1. tree.model.store.setValue(node.item, ‘name’/*取决于定义store时的label属性*/, newName)    

[javascript]  view plain copy

[javascript]  view plain copy

[javascript]  view plain copy

  1. tree.model.store.deleteItem(node.item)    

[javascript]  view plain copy

[javascript]  view plain copy

[javascript]  view plain copy

  1. tree.connect(tree, ‘onClick’, clickTreeNode);    
  2. function clickTreeNode(item/*点中节点对应的数据项*/, node/*点中的对象,这里node.item就是的第一个参数*/,evt/*事件*/)    
  3. {    
  4. …………….    
  5. }    

[javascript]  view plain copy

[javascript]  view plain copy

[javascript]  view plain copy

  1. dojo.connect(pMenu, ‘_openMyself’function(e){    
  2.     var node = dijit.getEnclosingWidget(e.target); /*node就是节点对象*/        
  3. });    

[javascript]  view plain copy

[javascript]  view plain copy

[javascript]  view plain copy

  1. tree.dndController.setSelection([node])    

[javascript]  view plain copy

[javascript]  view plain copy

[javascript]  view plain copy

  1. dojo.connect(tree.dndController, ‘onMouseDown’function(e){    
  2.     //如果你的树上有滚动条,请加入如下代码,否则如果你选中了节点后拖动滚动条会出现节点拖拽精灵    
  3.     if (dijit.getEnclosingWidget(e.target) == tree)    
  4.     {    
  5.         tree.dndController.mousedown = false;    
  6.         return;            
  7.     }    
  8.     //tree.dndController.mousedown为true表示允许拖拽,反之就是不允许,e为鼠标事件对象    
  9.     //tree的selectedNodes属性可以返回选中的节点列表,这里的代码表示每个选中节点的数据项中的type属性都是xxx才能拖动    
  10.     tree.dndController.mousedown = dojo.every(tree.selectedNodes, function(node){    
  11.         return (tree.model.store.getValue(node.item, ‘type’) == ‘xxx’)    
  12.     });      
  13. });    

[javascript]  view plain copy

[javascript]  view plain copy

[javascript]  view plain copy

  1. tree.checkItemAcceptance = function(target, source, position)    
  2. {    
  3. //target: DomNode 目标节点对应的dom, 用dijit.getEnclosingWidget(target)可以获得TreeNode对象    
  4. //source: dijit.tree.dndSource 被拖动的treeNode对象,是一个列表,因为tree允许一次拖动多个节点    
  5. //position: ‘over’, ‘before’, ‘after’    
  6. //返回true表示允许drop    
  7. }    

[javascript]  view plain copy

[javascript]  view plain copy

Leave a Comment

Your email address will not be published.