很多时候,我们想如此配置一个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,相信大家都能明白咋回事儿了。
这样写的目的是为了更简单的配置我们的控件,弊端是改变了函数原有的使用方法,编程了只适用于自己定义的规则。所以后期,这样的做法可能被改变。
本文探讨了ExtJS中Toolbar按钮handler作用域问题及解决方案。通过调整handler的定义方式和引入自定义函数来确保正确的this引用,避免了常见的作用域错误。


被折叠的 条评论
为什么被折叠?



