浅谈如何将项目中的 Dojo 从 1.6 升级至 1.8(4)升级过程中的建议与准则
![Rank: 8](images/default/star_level3.gif) ![Rank: 8](images/default/star_level3.gif)
- UID
- 1066743
|
![](http://images.eccn.com/silabs/silicon_chip_980x60_202203.jpg)
浅谈如何将项目中的 Dojo 从 1.6 升级至 1.8(4)升级过程中的建议与准则
升级过程中的建议与准则按照笔者的升级经验,有以下几点建议供您参考:
详细阅读与升级相关的 Dojo 版本的 Release note因为里面会有最权威的版本变化与升级注意事项。但需要注意的是,这些注意事项只会出现在当前版本的下一个版本的声明中。例如上文谈到的 acme 问题,它只出现在 Dojo1.7 的 Release note 里,在 Dojo 1.8 里是找不到相关声明的。图 2 摘自 Dojo1.7 的 Release note,主要描述了关于 selectorEngine 相关的改变。图 3 则摘自 Dojo 1.8 的 Release note, 描述了在做 Dojo 的升级操作时,有哪些地方需要特别注意。
图 2.Dojo1.7 中对 selectorEngine 所做的调整
图 3. Dojo 1.8 的 Release note 中关于 Dojo 迁移与升级的注意事项 充分利用互联网搜索服务项目的 Dojo 升级是一个普遍问题,因此可能自己遇到的升级问题别人也曾遇到过并且已有解决方案。所以应善于搜索别人已造好的“车轮”,减少不必要的时间成本。
Stack Overflow 是国外的一个面向程序员的专业 QA 站点,在这里可以找到各种与编程相关的问题以及高质量的答案。您可在解决问题之前先在该网站上进行查找相应问题的答案,该网站免费且不用注册,使用很方便。
图 4. Stack Overflow 网站 避免修改 Dojo 源码升级过程会遇到一些复杂问题,在解决这些问题时,尽量不要在 Dojo 源码这一层上进行改动。因为如果修改的代码被放在 Dojo 源码里,那么下次升级时这些修改的代码就会随着 Dojo 源码的替换而被移除。如果为解决问题不得不对 Dojo 源码进行修改,则可在业务代码中使用 Dojo.extend 来对源码中的方法进行修改。
此处以修改 dijit.Dialog 类的样式为例进行说明。假如当前项目需要对 dijt.Diaog 这个通用的对话框类的样式进行改变,为了遵循不修改 Dojo 源码的原则,我们可以有两种做法。第一种是创建子类继承 dijit.Dialog,再对子类进行修改。该做法在 Dojo 控件层之上引入自定义组件层,可能会破坏项目架构。第二种做法便是使用 Dojo.extend 来对 dijit.Dialog 进行修改,将 dijit.Dialog 的 template 换为项目自己定义的即可。如清单 6 所示。
清单 6. 使用 Dojo.extend 间接修改 Dialog 类1
2
3
4
| dojo.extend(dijit.Dialog, {
templateString: dojo.cache("dojoCustom",
"templates/Dialog.html")
});
|
Dojo.extend 与 Java 反射类似,都是在运行时对类的结构进行了修改。之后由此类生成的对象,都会受到之前对类所做修改的影响。因此,Dialog 在被修改 template 后,由其所产生的所有 Dialog 对象,都会使用新的 template 进行展现,从而显示出新的样式。
避免使用 Dojo 源代码中的私有属性和方法众所周知,JavaScript 的属性和方法不像 Java 等语言那样具有访问权限。因此理论上我们可以随意访问一个对象的方法和属性。但由于目前 Dojo 的版本变化较快,其私有属性和方法也时常变化,这里的“私有”指的是变量前面加下划线标识的。项目代码中一旦使用了这些私有属性和方法,则在下一次项目 Dojo 升级后,则很可能出现问题。例如,新版本的 Dojo 直接删除了某个私有方法,而这个私有方法恰好被项目所使用。正确的做法应是直接使用 Dojo 源码中的公有方法和属性(不带下划线标识),因为 Dojo 的公开方法和属性相对稳定,可以避免因 Dojo 升级所引起的问题。
还是以 dijit.Dialog 为例进行说明。Dialog 有一个私有方法_size(),用于调整 dialog 里面的内容而使 Dialog 展现得更完整美观。这个方法在 Dojo 1.6 与 Dojo 1.8 中的定义并不相同。如清单 7、8 所示。我们在对 dialog 进行调整时,不能直接使用这个私有方法,而应该使用 resize()或 show()这些公开方法。公开方法的内部会调用这个私有方法,并在这个私有方法发生改变时,也做适当调整,使该公开方法自身的作用保持不变。
清单 7. Dojo 1.8 中_size()方法的定义1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
| _size: function(){
this._checkIfSingleChild();
if(this._singleChild){
if(typeof this._singleChildOriginalStyle != "undefined"){
this._singleChild.domNode.style.cssText = this._singleChildOriginalStyle;
delete this._singleChildOriginalStyle;
}
}else{
domStyle.set(this.containerNode, {
width:"auto",
height:"auto"
});
}
var bb = domGeometry.position(this.domNode);
var viewport = winUtils.getBox(this.ownerDocument);
viewport.w *= this.maxRatio;
viewport.h *= this.maxRatio;
if(bb.w >= viewport.w || bb.h >= viewport.h){
var containerSize = domGeometry.position(this.containerNode),
w = Math.min(bb.w, viewport.w) - (bb.w - containerSize.w),
h = Math.min(bb.h, viewport.h) - (bb.h - containerSize.h);
if(this._singleChild && this._singleChild.resize){
if(typeof this._singleChildOriginalStyle == "undefined"){
this._singleChildOriginalStyle
= this._singleChild.domNode.style.cssText;
}
this._singleChild.resize({w: w, h: h});
}else{
domStyle.set(this.containerNode, {
width: w + "px",
height: h + "px",
overflow: "auto",
position: "relative"
});
}
}else{
if(this._singleChild && this._singleChild.resize){
this._singleChild.resize();
}
}
},
|
清单 8. Dojo 1.6 中_size()方法的定义1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
| _size: function(){
this._checkIfSingleChild();
if(this._singleChild){
if(this._singleChildOriginalStyle){
this._singleChild.domNode.style.cssText =
this._singleChildOriginalStyle;
}
delete this._singleChildOriginalStyle;
}else{
dojo.style(this.containerNode, {
width:"auto",
height:"auto"
});
}
var mb = dojo._getMarginSize(this.domNode);
var viewport = dojo.window.getBox();
if(mb.w >= viewport.w || mb.h >= viewport.h){
var w = Math.min(mb.w, Math.floor(viewport.w * 0.75)),
h = Math.min(mb.h, Math.floor(viewport.h * 0.75));
if(this._singleChild && this._singleChild.resize){
this._singleChildOriginalStyle
= this._singleChild.domNode.style.cssText;
this._singleChild.resize({w: w, h: h});
}else{
dojo.style(this.containerNode, {
width: w + "px",
height: h + "px",
overflow: "auto",
position: "relative"
});
}
}else{
if(this._singleChild && this._singleChild.resize){
this._singleChild.resize();
}
}
},
|
准确定位当前问题是升级导致的还是残留问题解决这两类问题时,调试代码的侧重点是不同的。升级导致的问题更关注 Dojo 底层源码,而系统残留问题一般与业务代码相关。定位问题类型的方法有多种,其中一种比较直观的就是将升级后的系统与升级前的系统做对照。这种对照式调试方式应该贯穿于整个升级过程。 |
|
|
|
|
|