有时候我们会写一个基类dojo小部件用以实现一些通用的功能,然后让其他小部件继承该widget,有时候需要在父类和子类中的多个生命周期中写不同的代码以完成不同的功能,使得我对小部件的生命周期有点混乱,于是准备写一个简单的父子继承的小部件研究下其生命周期。
首先定义父类iSpring.widgets.father.Father,其模板文件很简单,如下所示:
<div style="color:blue;">内容</div>
父类的js代码如下:
dojo.provide("iSpring.widgets.father.Father");
dojo.require("dijit._Widget");
dojo.require("dijit._Templated");
dojo.require("dojo.cache");
dojo.declare("iSpring.widgets.father.Father",[dijit._Widget,dijit._Templated],{
_module:"iSpring.widgets.father",
templateString:dojo.cache("iSpring.widgets.father","templates/Father.html"),
constructor:function(){
console.log("Father.constructor");
},
postMixInProperties:function(){
console.log("Father.postMixInProperties");
},
postCreate:function(){
console.log("Father.postCreate");
},
startup:function(){
console.log("Father.startup");
}
});
然后写一个子类iSpring.widgets.son.Son继承自iSpring.widgets.father.Father,由于是继承了父类,所以就没有写Son小部件的模板文件,其js代码如下:
dojo.provide("iSpring.widgets.son.Son");
dojo.require("dijit._Widget");
dojo.require("dijit._Templated");
dojo.require("dojo.cache");
dojo.require("iSpring.widgets.father.Father");
dojo.declare("iSpring.widgets.son.Son",[iSpring.widgets.father.Father],{
_module:"iSpring.widgets.son",
constructor:function(){
console.log("Son.constructor");
},
postMixInProperties:function(){
console.log("Son.postMixInProperties");
},
postCreate:function(){
console.log("Son.postCreate");
},
startup:function(){
console.log("Son.startup");
}
});
在网页中创建Son并显示的前端代码如下:
!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html"/>
<meta name="charset" content="utf-8"/>
<title></title>
<script type="text/javascript">
dojoConfig = {
parseOnLoad:true,
baseUrl:'./',
modulePaths: { 'iSpring': 'iSpring' }
};
</script>
<script type="text/javascript" src="http://localhost/jsapi28/"></script>
<link type="text/css" rel="stylesheet" href="http://localhost/jsapi28/js/dojo/dijit/themes/claro/claro.css" />
<script type="text/javascript">
dojo.require("iSpring.widgets.son.Son");
function init(){
var son = new iSpring.widgets.son.Son();
son.placeAt(dojo.body());
}
dojo.addOnLoad(init);
</script>
</head>
<body class="claro">
</body>
</html>
通过localhost的方式打开网页可以看到控制台中的输出结果如下:
也就是会所首先调用了父类的构造函数,然后调用了子类的构造函数,没有调用父类的postMixInProperties以及postCreate,调用了子类的。
现在我们把子类js代码中的postMixInProperties函数删除,父类js代码不变,子类js代码变为如下:
dojo.provide("iSpring.widgets.son.Son");
dojo.require("dijit._Widget");
dojo.require("dijit._Templated");
dojo.require("dojo.cache");
dojo.require("iSpring.widgets.father.Father");
dojo.declare("iSpring.widgets.son.Son",[iSpring.widgets.father.Father],{
_module:"iSpring.widgets.son",
constructor:function(){
console.log("Son.constructor");
},
postCreate:function(){
console.log("Son.postCreate");
},
startup:function(){
console.log("Son.startup");
}
});
保存后刷新网页,控制台中的输出结果如下:
我们发现在分别调用了父类、子类的构造函数之后,紧接着调用了父类的postMixInProperties,然后调用的是子类的postCreate。
现在我们再把子类js代码中的postMinInProperties代码添加上,并在其中添加this.inherited(arumnets)语句,父类js代码不变,子类js代码变为如下:
dojo.provide("iSpring.widgets.son.Son");
dojo.require("dijit._Widget");
dojo.require("dijit._Templated");
dojo.require("dojo.cache");
dojo.require("iSpring.widgets.father.Father");
dojo.declare("iSpring.widgets.son.Son",[iSpring.widgets.father.Father],{
_module:"iSpring.widgets.son",
constructor:function(){
console.log("Son.constructor");
},
postMixInProperties:function(){
this.inherited(arguments);
console.log("Son.postMixInProperties");
},
postCreate:function(){
console.log("Son.postCreate");
},
startup:function(){
console.log("Son.startup");
}
});
保存后刷新网页,控制台中的输出结果如下:
可以发现,在分别调用了父类、子类的构造函数之后,又调用了父类、子类的postMixInProperties,最后调用的是子类的postCreate
最后,我们把子类js代码中的postMixInProperties和postCreate都删除,父类代码不变,子类的代码变为如下:
dojo.provide("iSpring.widgets.son.Son");
dojo.require("dijit._Widget");
dojo.require("dijit._Templated");
dojo.require("dojo.cache");
dojo.require("iSpring.widgets.father.Father");
dojo.declare("iSpring.widgets.son.Son",[iSpring.widgets.father.Father],{
_module:"iSpring.widgets.son",
constructor:function(){
console.log("Son.constructor");
},
startup:function(){
console.log("Son.startup");
}
});
保存后刷新页面,在控制台中的输出结果如下:
发现在调用了父类、子类的构造函数之后,又调用了父类的postMixInProperties以及postCreate。
通过以上的实验,我们可以得知:基于继承的dojo小部件的生命周期类似于C#等高级语言中类的生命周期,首先要调用父类的构造函数,然后调用子类的构造函数,下面就进入了逐个事件点调用,如果对于某个事件点(比如postMixInProperties),子类没有提供处理函数,就默认调用父类的处理函数,如果子类提供了处理函数,那么就会覆盖父类的同名方法,要想在该处理函数中调用父类的方法就要显式的调用this.inherited(arguments)语句。这样就完成了一个事件点的处理,然后继续以同样的方式处理下一个事件点(比如postCreate)。也就是说在基于继承的dojo小部件中,也存在类似于高级语言中的函数继承、函数覆盖重写等功能。