grid中的数据是如何渲染上去的,如果你已经看过ext源码请忽略此文,因为她会浪费你的青春。
对于刚接触ext的同学来说可能会有疑问:
grid中的数据是怎么渲染上去的 或 grid和store是如何联系在一起的?
1.我们先看一下表格的几个重要的配置store, columns, colModel, sm, viewConfig…
store: grid的数据来源,我们可以将其简单的看成一个ajax请求返回的数据(同时具有一些事件(datachange, load, add, clear and so on…))
columns: 控制grid的表头、显示哪个字段以及如何显示(renderer方法)
colModel: 管理columns,一般不需要覆写这个配置
sm: 记录前面的复选框
viewConfig: GridView的一些配置
GridPanel就是一张白纸,提供给store, column, colModel, sm, GrieView尽情的书写而已
2.一般独立的组件都有自己的一套模板(tpl),在onRender方法(或者onRender调用的方法)中将特定的数据apply到tpl上,
然后追加到页面中就是我们看到的效果
接下来我们看一下GridPanel的onRender方法,因为我们自定义的html模板最终是通过onRender方
法的调用追加到页面上的
onRender : function(ct, position){
Ext.grid.GridPanel.superclass.onRender.apply(this, arguments);
...
...
var view = this.getView(); // view就是grid的视图
view.init(this); // 传递一个grid的引用给GridView
view.render();
...
}
getView : function(){
if(!this.view){
this.view = new Ext.grid.GridView(this.viewConfig);
}
return this.view;
}
3.现在我们看一下GridView核心方法的调用
/* ----------------------------------- Core Specific -------------------------------------------*/
init:function(grid){
this.grid=grid;
// 创建表格的各种模板(header body footer)
this.initTemplates();
// 将GridView操作表格列的一些方法与store的一些事件对应起来,这样store的数据改变时GridView就能自动更新了
this.initData(grid.store,grid.colModel);
// 绑定表头的点击进行排序的事件
this.initUI(grid);
}
init这个方法就是上面第2步的时候GridPanel的onRender方法中调用的,
GridView与Store的关联可以看下面的代码:
ds.on({
scope: this,
load: this.onLoad,
datachanged: this.onDataChange,
add: this.onAdd,
remove: this.onRemove,
update: this.onUpdate,
clear: this.onClear
});
ds就是store, store加载到数据后会触发自身的datachanged事件,然后会调用GridView的onDataChange,然后会调用refresh
方法调用是这样的:onDataChange -> refresh -> renderBody -> renderRows -> doRender
onDataChange:function(){
this.refresh();
...
}
refresh:function(headersToo){
...
varresult=this.renderBody();// 看她
this.mainBody.update(result).setWidth(this.getTotalWidth());// 将renderRows组装好的html元素更新到页面上
...
}
renderBody:function(){
varmarkup=this.renderRows()||' ';// 这步就是将store中的数据添加到模板中,生成dom节点
returnthis.templates.body.apply({rows:markup});
}
===doRender !important===
doRender方法的角色就是一个码农,按照tpl的格式将数据填充到每一列每一行,最终返回一个超级大的组装好的dom节点
看一下doRender方法,关注有注释的部分就行了
doRender:function(cs,rs,ds,startRow,colCount,stripe){
// ct是生成每一列的模板 rt是生成每一行的模板
varts=this.templates,ct=ts.cell,rt=ts.row,last=colCount-1;
...
varbuf=[],cb,c,p={},rp={tstyle:tstyle},r;
for(varj=0,len=rs.length;j<len;j++){
...
for(vari=0;i<colCount;i++){
...
p.css=i===0?'x-grid3-cell-first':(i==last?'x-grid3-cell-last':'');
p.value=c.renderer.call(c.scope,r.data[c.name],p,r,rowIndex,i,ds);
...
cb[cb.length]=ct.apply(p);// 列模板的渲染
}
...
rp.cells=cb.join('');
buf[buf.length]= rt.apply(rp);// 行模板的渲染
}
returnbuf.join('');// 最终生成的有数据的表格的html片段
}