很多时候,我们想如此配置一个GridPanel或TreePanel的tbar:
MyTreePanel = Ext.extend(Ext.grid.TreePanel, { tbar : ['->', { iconCls : "x-tree-expand-all", tooltip : '展开所有菜单', handler : function() { this.getRootNode().expand(true, true); } }}, { iconCls : "x-tree-refresh", tooltip : '刷新', handler : this.refresh() }]}
请注意为tbar中的第一个button配置的handler,结合对JavaScript中this的理解,会导致什么问题?我们在使用MyTreePanel的时候,通常是在页面也代码或者Window对象中new MyTreePanel。这样,按钮的handler的scope其实是window,所有function里边的this也是window对象,必然导致错误。有人说,这样写:function(){...}.createDelegate(this),换汤不换药,this指的同样是window对象。
如果我们在MyTreePanel中的一个函数中定义tbar,如:
initToolbar : function(){ this.tbar = [ { iconCls : "x-tree-expand-all", tooltip : '展开所有菜单', handler : function() { this.getRootNode().expand(true, true); } ] }
修改一下handler: function(){...}.createDelegate(this);这样就得以解决问题。
但是我们打算写一个通用的函数来处理这个问题,以便于我们编程,或者说,我们就是想装逼一下,搞通这个问题:我们不放这么写:
/** * 初始化toolbar的handler */ initToolbarListeners : function() { var items; // 处理tbar if (this.getTopToolbar()) { this.getTopToolbar().cascade(this.adaptCmpHandlerScope, this); } // 处理bbar if (this.getFooterToolbar()) { this.getFooterToolbar().cascade(this.adaptCmpHandlerScope, this); } if(this.getBottomToolbar()){ this.getBottomToolbar().cascade(this.adaptCmpHandlerScope, this); } },
/** * @private 改变 */ adaptCmpHandlerScope : function(cmp) { if (cmp.handler) { if (Ext.isFunction(cmp.handler)) { cmp.handler = cmp.handler.createDelegate(this); } else if (Ext.isString(cmp.handler)) { cmp.handler = this[cmp.handler].createDelegate(this); } } },
这样配置完各种bar之后,调用这个函数就可以解决我们之前说的问题。
我们只说了第一个button,看第二个button,他直接调用this.refresh(),而this怎么地只得都是window,所有这样肯定是不行的,所有我们的处理方法编程这样,handler : "save",然后参看adaptCmpHandlerScope函数中else if,相信大家都能明白咋回事儿了。
这样写的目的是为了更简单的配置我们的控件,弊端是改变了函数原有的使用方法,编程了只适用于自己定义的规则。所以后期,这样的做法可能被改变。