【easyui】treegrid逐级加载源码
当初看这源码的目的是:
1、treegrid是怎么实现逐级加载树结构的。
解: 见demo,主要就是点击节点的时候会请求后台。
2、treegrid加载后,第二次展开节点会不会再次请求后台。
解:第二次展开节点不会再请求后台。
没记错的话,貌似是第一次点击节点 –> 请求后台 –> 根据响应的数据构建div,形成树结构。
再第二次点击的时候:点击节点所在的div的下一个同级div的class是tr.treegrid-tr-tree的话,表示已加载过其子节点数据。则不需要再次请求后台。
3、对js不是那么的熟悉,顺便学习下js,看treegrid的实现思路和了解一些对js不知道的东西。
a) 不管是easyui还是jquery都大量使用了回调函数。
b) 都不只直接用的function的参数,而是通过js内置的arguments[i]来判断运用。(jquery貌似用的多,在深/浅复制那)
如果对js不是很清楚,可以大致浏览下 JS总结 – 乱 。
// demo.js $(function() { $('#datagrid').treegrid({ url:'loanOrganization/queryLoanOrganizationJSONList', idField:'id', treeField:'text', nowrap: false, rownumbers: true, toolbar: '#toolBar', animate:true, collapsible:true, columns:[[ {field:'id',title:'合作机构id',width:300,hidden:true}, {field:'text',title:'合作机构名称',width:300,iconCls:"icon-sum"}, {field:'ext1',title:'子节点数量',width:200, formatter: function(value,row,index){ return value =='0' ? '' : value; } }, {field:'ext2',title:'排序字段',width:100,sortable:true} ]], loadFilter: function(result){ return result.data;}, onClickRow:function(row){ console.info("onClickRow:当用户点击一个节点时触发."); }, onBeforeLoad:function(row, param){ console.info("onBeforeLoad:一个请求去加载数据之前触发, 返回false将取消加载动作."); }, onLoadSuccess:function(row,data){ console.info("onLoadSuccess:数据加载成功之后触发."); }, onLoadError:function(){ console.info("onLoadError:数据加载失败之后触发,arguments 参数和jQuery.ajax的error函数一样."); }, onBeforeExpand:function(row){ //每次展开前都会调用 //动态设置展开查询的url var url = 'loanOrganization/queryLoanOrganizationJSONList?parentId='+row.id; $("#datagrid").treegrid("options").url = url; return true; //返回false表示停止展开节点 }, onExpand : function(row){ //每次展后都会调用;传入的row已经包含了 children var children = $("#datagrid").treegrid('getChildren',row.id); if(children.length<=0){ row.leaf=true; $("#datagrid").treegrid('refresh', row.id); } }, onContextMenu: function(e,row){ e.preventDefault(); $(this).treegrid('unselectAll'); $(this).treegrid('select', row.id); $('#mm').menu('show', { left: e.pageX, top: e.pageY }); }, onDblClickRow: function(row){ edit(); } }); }); //$(function(){...}) end
Easyui.js源码 版本:1.3.2
function _6db(_6dc,_6dd){ //内部函数_6df(cc) var opts=$.data(_6dc,"treegrid").options; var tr=opts.finder.getTr(_6dc,_6dd); var hit=tr.find("span.tree-hit"); var row=find(_6dc,_6dd); if(hit.length==0){ return; } if(hit.hasClass("tree-expanded")){ return; } if(opts.onBeforeExpand.call(_6dc,row)==false){// 触发onBeforeExpand return; } hit.removeClass("tree-collapsed tree-collapsed-hover").addClass("tree-expanded"); hit.next().addClass("tree-folder-open"); // 点击节点所在的div的下一个同级div的class是tr.treegrid-tr-tree的话,表示已加载过其子节点数据。则不需要再次请求后台。 var _6de=tr.next("tr.treegrid-tr-tree"); // if为true时,不会再次请求后台(即该节点的子节点数据已被加载过) if(_6de.length){ var cc=_6de.children("td").children("div"); _6df(cc); }else{ // _6de==Object[] 要请求后台加载数据 _6a8(_6dc,row[opts.idField]); var _6de=tr.next("tr.treegrid-tr-tree"); var cc=_6de.children("td").children("div"); cc.hide(); // _699() 内部有ajax请求后台 _699(_6dc,row[opts.idField],{id:row[opts.idField]},true,function(){ if(cc.is(":empty")){ _6de.remove(); }else{ _6df(cc); } }); } function _6df(cc){ row.state="open"; if(opts.animate){ cc.slideDown("normal",function(){ $(_6dc).treegrid("autoSizeColumn"); _69a(_6dc,_6dd); opts.onExpand.call(_6dc,row); }); }else{ cc.show(); $(_6dc).treegrid("autoSizeColumn"); _69a(_6dc,_6dd); opts.onExpand.call(_6dc,row); } }; };
function find(_6d6,_6d7){ // _6d7 == idField var opts=$.data(_6d6,"treegrid").options; var data=$.data(_6d6,"treegrid").data; var cc=[data]; while(cc.length){ //shift() 方法用于把数组的第一个元素从其中删除,并返回第一个元素的值。 var c=cc.shift(); for(var i=0;i<c.length;i++){// var node=c[i]; if(node[opts.idField]==_6d7){ return node; }else{ if(node["children"]){ cc.push(node["children"]); } } } } return null; };
function _699(_6b7,_6b8,_6b9,_6ba,_6bb){ var opts=$.data(_6b7,"treegrid").options; var body=$(_6b7).datagrid("getPanel").find("div.datagrid-body"); if(_6b9){ opts.queryParams=_6b9; } var _6bc=$.extend({},opts.queryParams); if(opts.pagination){ $.extend(_6bc,{page:opts.pageNumber,rows:opts.pageSize}); } if(opts.sortName){ $.extend(_6bc,{sort:opts.sortName,order:opts.sortOrder}); } var row=find(_6b7,_6b8); if(opts.onBeforeLoad.call(_6b7,row,_6bc)==false){ return; } var _6bd=body.find("tr[node-id="+_6b8+"] span.tree-folder"); _6bd.addClass("tree-loading"); $(_6b7).treegrid("loading"); //请求加载tree数据,根据treegrid定义的url(在onBeforeExpand中修改了的url)。 var _6be=opts.loader.call(_6b7,_6bc, function(data){ // loader中ajax成功请求的回调函数 _6bd.removeClass("tree-loading"); $(_6b7).treegrid("loaded"); _6af(_6b7,_6b8,data,_6ba); if(_6bb){ _6bb(); } },function(){ _6bd.removeClass("tree-loading"); $(_6b7).treegrid("loaded"); opts.onLoadError.apply(_6b7,arguments); if(_6bb){ _6bb(); } }); if(_6be==false){ _6bd.removeClass("tree-loading"); $(_6b7).treegrid("loaded"); } };
$.fn.treegrid.defaults=$.extend({},$.fn.datagrid.defaults, { treeField:null, animate:false, singleSelect:true, view:_709, //_73a:请求参数 _73b:ajax success回调函数 _73c:ajax error回调函数 loader:function(_73a, _73b, _73c){ var opts=$(this).treegrid("options"); if(!opts.url){ return false; } $.ajax({type:opts.method, url:opts.url, data:_73a, dataType:"json", success:function(data){ _73b(data); }, error:function(){ _73c.apply(this,arguments); } }); },loadFilter:function(data,_73d){ return data; }, ...
function _6af(_6b0,_6b1,data,_6b2){ var opts=$.data(_6b0,"treegrid").options; var dc=$.data(_6b0,"datagrid").dc; data=opts.loadFilter.call(_6b0,data,_6b1); var node=find(_6b0,_6b1); if(node){ var _6b3=opts.finder.getTr(_6b0,_6b1,"body",1); var _6b4=opts.finder.getTr(_6b0,_6b1,"body",2); var cc1=_6b3.next("tr.treegrid-tr-tree").children("td").children("div"); var cc2=_6b4.next("tr.treegrid-tr-tree").children("td").children("div"); }else{ var cc1=dc.body1; var cc2=dc.body2; } if(!_6b2){ $.data(_6b0,"treegrid").data=[]; cc1.empty(); cc2.empty(); } if(opts.view.onBeforeRender){ // onBeforeRender中处理了treeJson opts.view.onBeforeRender.call(opts.view,_6b0,_6b1,data); } opts.view.render.call(opts.view,_6b0,cc1,true); opts.view.render.call(opts.view,_6b0,cc2,false); if(opts.showFooter){ opts.view.renderFooter.call(opts.view,_6b0,dc.footer1,true); opts.view.renderFooter.call(opts.view,_6b0,dc.footer2,false); } if(opts.view.onAfterRender){ opts.view.onAfterRender.call(opts.view,_6b0); } opts.onLoadSuccess.call(_6b0,node,data); if(!_6b1&&opts.pagination){ var _6b5=$.data(_6b0,"treegrid").total; var _6b6=$(_6b0).datagrid("getPager"); if(_6b6.pagination("options").total!=_6b5){ _6b6.pagination({total:_6b5}); } } _69a(_6b0); _6a2(_6b0); $(_6b0).treegrid("autoSizeColumn"); };
function _69a(_69b,_69c){ var opts=$.data(_69b,"datagrid").options; var dc=$.data(_69b,"datagrid").dc; if(!dc.body1.is(":empty")&&(!opts.nowrap||opts.autoRowHeight)){ if(_69c!=undefined){ var _69d=_69e(_69b,_69c); for(var i=0;i<_69d.length;i++){ _69f(_69d[i][opts.idField]); } } } $(_69b).datagrid("fixRowHeight",_69c); function _69f(_6a0){ var tr1=opts.finder.getTr(_69b,_6a0,"body",1); var tr2=opts.finder.getTr(_69b,_6a0,"body",2); tr1.css("height",""); tr2.css("height",""); var _6a1=Math.max(tr1.height(),tr2.height()); tr1.css("height",_6a1); tr2.css("height",_6a1); }; };
function _6a2(_6a3){ var dc=$.data(_6a3,"datagrid").dc; var opts=$.data(_6a3,"treegrid").options; if(!opts.rownumbers){ return; } dc.body1.find("div.datagrid-cell-rownumber").each(function(i){ $(this).html(i+1); }); };
function _69e(_6c6,_6c7){ var opts=$.data(_6c6,"treegrid").options; var body=$(_6c6).datagrid("getPanel").find("div.datagrid-view2 div.datagrid-body"); var _6c8=[]; if(_6c7){ _6c9(_6c7); }else{ var _6ca=_6c1(_6c6); for(var i=0;i<_6ca.length;i++){ _6c8.push(_6ca[i]); _6c9(_6ca[i][opts.idField]); } } function _6c9(_6cb){ var _6cc=find(_6c6,_6cb); if(_6cc&&_6cc.children){ for(var i=0,len=_6cc.children.length;i<len;i++){ var _6cd=_6cc.children[i]; _6c8.push(_6cd); _6c9(_6cd[opts.idField]); } } }; return _6c8; }
var _709 = $.extend({},$.fn.datagrid.defaults.view, {onBeforeRender : function(_72e, _72f, data) { if (!data) { return false; } var opts = $.data(_72e, "treegrid").options; if (data.length == undefined) { if (data.footer) { $.data(_72e, "treegrid").footer = data.footer; } if (data.total) { $.data(_72e, "treegrid").total = data.total; } data = this.transfer(_72e, _72f, data.rows); } else { function _730(_731, _732) { for ( var i = 0; i < _731.length; i++) { var row = _731[i]; row._parentId = _732; if (row.children && row.children.length) { _730(row.children,row[opts.idField]); } } }; _730(data, _72f); } var node = find(_72e, _72f); if (node) { if (node.children) { // concat() 方法用于连接两个或多个数组。 // 该方法不会改变现有的数组,而仅仅会返回被连接数组的一个副本。 node.children = node.children.concat(data); } else { node.children = data; } } else { $.data(_72e, "treegrid").data = $.data(_72e, "treegrid").data.concat(data); } if (!opts.remoteSort) { this.sort(_72e, data); } this.treeNodes = data; this.treeLevel = $(_72e).treegrid("getLevel", _72f); },...}
作者:
VergiLyn
Github: https://github.com/vergilyn
出处: http://www.cnblogs.com/VergiLyn/
备注: 一只凄惨的中华田园犬.
Github: https://github.com/vergilyn
出处: http://www.cnblogs.com/VergiLyn/
备注: 一只凄惨的中华田园犬.