今天下午的时候,同事说发现了一个问题.Ext4做好页面,重新单击菜单动态加载一次,树就消失了.
于是,我帮忙看了一下,一开始没认为是什么大问题.但是越调发现越不对.到快下班的时候,没有什么思路.于是不再随便看了.好好Debug一下Ext源代码来找问题.到晚上七点半.终于问题搞定了.这次Debug的过程事后想想真是过瘾.因为不仅仅是解决了一个bug.
最重要的是对javascript更进一步有所了解了.
晚上回家,总觉得得记下来,不是记录技术方面的收获,因为知识点变来变去就那么点东西.都是以前就知道的东西,只不过变了一个样子就不会了.我想写写这次调试过程中的自己的一些猜测还有事后对于程序员的看法.
首先描述一下问题.
Ext实现简单的动态加载菜单.
点击菜单,在TabPanel上加载一个Tab窗体,窗体里面有一个tree控件.
第一次加载没问题,但是再点击一次的话
对,树就神奇的消失了.
代码的话:
<!-- lang: js -->
//首先是动态加载菜单的代码段
listeners: {
itemclick: function (_this, record, item, index, e, eOpts) {
if (record.data.leaf) {
var MainContiner = Ext.getCmp("MainContiner");
var action = Ext.create(record.raw.action.package, record.raw.action);
if (!MainContiner.child(action) ||
record.raw.action.package == "app.actionPanel.ActionPanel")
{
MainContiner.add(action);
}
MainContiner.setActiveTab(action);
}
}
}
<!-- lang: js -->
//然后是窗体的定义片段的构造函数
constructor: function () {
var marktypeTree = Ext.create("app.mark.markTree",{
callback:function(data){
if (data != null) {
Ext.getCmp("MainContiner").child("#staffTypeID").child("#panelGridId").treeNode.push(data)
Ext.getCmp("MainContiner").child("#staffTypeID").child("#panelGridId").child("#markTypeGrid").store.reload({
params: {
_id: data
}
})
}
}
});
this.items[0].items.push(marktypeTree);
this.callParent(arguments);
var a=0;
},
第一眼我看到这个问题,先怀疑的是树控件被释放掉了.或者树控件被重写了.但是检查了一遍代码,发现没有这个问题.然后debug看两次单击,窗体到底有什么变化.发现点击两次,panel下面会加入两颗树控件.
而且单击次数越多,加入的数量越多.立马就不明白了.按理说第二次单击窗体判断同一个窗体后,不会再加入到tab中.但是树怎么就进去了呢.
然后调试了很长时间,突然有了一个想法…于是写了一个小例子………
<!-- lang: js -->
function A(){
}
function B(){
this.b=1;
this.arr=[];
this.obj={};
}
A.prototype = new B();
var a = new A();
a.b//这个变量是可以通过圆形查找查到的.
a.c=1;
a.c//这个c变量在a对象下面,
a.arr.push(1);//这个地方就有意思了.
//a.arr 会引用到原型里面.push一下后.变量就被增加到 原型对象里面了.
//对了.这个地方就是js里面的引用.
//对象也符合这个引用.
//换句话说
var a2 = new A();
a2.arr.length;//这里length是1.因为原型域是共享的域.
这里反思一下.一直以来,把javascript当做面向对象去学的话.原型会类比继承.但是javascript毕竟不是面向对象的.所以造成这个问题给疏忽了.如果从原型角度来考虑.这就是基本知识点.
问题改过来了.我想到了很多别的问题.
首先对于javascript.再强调一次.把js当做面向对象语言去学是种耍流氓的行为.早晚碰壁.javascript是原型函数式语言.
我可以操作原型域实现面向对象实现不了有意思的功能.如果是面向对象的思维方式,上面的问题就是Bug.但是这不是.这是一个很有趣的探索.
其次,关于如何解决bug的问题.感觉跳错需要一种回归原点的能力.就是能够把目前的问题回退到问题最初的能力.
很多人调试程序.编译器报错了,就粘贴出来错误百度.然后顺着往后找错.找不到就说这问题没法解决.或者就算找到了.大多通过增加代码的方式去调试.各种条件一限定.不出错了.但是你问为什么出错啊?xx的问题….基本都是很表面的答案.
我觉得写代码,应该能站到设计者的角度去写.你用Ext.就得站到Ext设计者角度去写代码.理解Ext代码运行机制.同样的bug.有太多的方式可以解决.但是从Ext的运行机制上去考虑解决的方法就没有那么多了.
如何回归代码设计的原点,通过非干预的手段来解决问题.我觉得这种理解能力.是一个程序员成长到一定程度会遇到的新的瓶颈.