经典js类继承方法
/*
* @param subClass Function 子类
* @param superClass Function 父类
*/
utility.inherits = function (subClass, superClass) {
var F = function () {
};
F.prototype = superClass.prototype;
subClass.prototype = new F();
subClass.prototype.constructor = subClass;
subClass.superclass = superClass.prototype;
if (superClass.prototype.constructor == Object.prototype.constructor) {
superClass.prototype.constructor = superClass;
}
}
</pre><pre name="code" class="javascript">来自于JavaScript设计模式的Interface类
// 接口类
/*
* @param name String 接口的名字
* @param methods Array 接口里面定义的方法
*/
utility.Interface = function (name, methods) {
//如果购造函数的参数不等于2个,那么抛出异常
if (arguments.length != 2) {
throw new Error("Interface constructor called with " + arguments.length +
" arguments,but expected exactyl 2.")
}
this.name = name;
this.methods = [];
//方法数组,保证传进来的methods数组中,每一个元素都是字符串类型
for (var i = 0, len = methods.length; i < len; i++) {
if (typeof methods[i] !== "string") {
throw new Error("Interface constructor expects methods names to bo " +
" passed in asastring.");
}
this.methods.push(methods[i]);
}
}
//接口实现方法
utility.Interface.ensureImplements = function (object) {
//如果参数少于2个,抛出异常,object是待判断实现接口的对象
if (arguments.length < 2) {
throw new Error("Function Interface.ensureImplements 被调用,传入 " + arguments.length +
" 个参数,至少需要2个参数。");
}
for (var i = 1, len = arguments.length; i < len; i++) {
//inter_face为接口,一定要实现Interface类
//书中使用interface,因是JavaScript中保留字,所以暂替换为inter_face
var inter_face = arguments[i];
if (inter_face.constructor !== utility.Interface) {
throw new Error("Function Interface.ensureImplements:第二个以及之后的参数必须是Interface的实例。");
}
for (var j = 0, methodsLen = inter_face.methods.length; j < methodsLen; j++) {
//对象中是否含有接口中定义的方法
var method = inter_face.methods[j];
if (!object[method] || typeof object[method] !== 'function') {
throw new Error("Function Interface.ensureImplements: 对象 " +
" 没有实现接口 " +
inter_face.name +
" 的方法 " +
method);
}
}
}
}
//接口属性检测
utility.Interface.ensureProperty = function (object, properties) {
for (var j = 0, len = properties.length; j < len; j++) {
if (!object[properties[j]]) {
throw new Error("Function Interface.ensureProperty: 对象中不存在 " +
properties[j] +
" 属性 ");
}
}
}
父类,定义并实现一个接口
/**
* PageAbstract类构造函数。
*/
_common.PageAbstract = function () {
//定义Page的接口和需要实现的方法
var PageInterface = new utility.Interface('Page', ['initialize', 'render', 'initializeDOM', 'destroyDOM']);
utility.Interface.ensureImplements(this, PageInterface);
utility.Interface.ensureProperty(this, ['action', 'handler', 'ajaxCallBack']);
this.initEvents(this.handler);
var that = this;
//窗口unload时候释放资源
$(window).on('unload', function () {
that.dispose();
});
//如果实现了initializeDOM方法就执行
if (this.initializeDOM && (typeof this.initializeDOM == 'function')) {
this.initializeDOM();
}
//如果实现了initialize方法就执行
if (this.initialize && (typeof this.initialize == 'function')) {
this.initialize();
}
//如果实现了render方法就执行
if (this.render && (typeof this.render == 'function')) {
this.render();
}
}
//类似angularJS的命令式绑定事件方法
_common.PageAbstract.prototype.initEvents = function (handlers) {
var that = this;
var eventsCommon = ["click", "dblclick", "mousedown", "mouseup", "mouseover", "mousemove", "mouseout", "mouseenter", "mouseleave", "keypress", "keydown", "keyup"];
var eventsBody = ["abort", "beforeunload", "error", "load", "move", "resize", "scroll", "stop", "unload"];
var eventsForm = ["blur", "change", "focus", "reset", "submit"];
var eventsMarquee = ["bounce", "finish", "start"];
var eventsEdit = ["beforecopy", "beforecut", "beforeeditfocus", "beforepaste", "beforeupdate", "contextmenu", "copy", "cut", "drag", "dragdrop", "dragend", "dragenter", "dragleave", "dragover", "dragstart", "drop", "losecapture", "paste", "select", "selectstart"];
var eventsData = ["afterupdate", "cellchange", "dataavailable", "datasetchanged", "datasetcomplete", "errorupdate", "rowenter", "rowexit", "rowsdelete", "rowsinserted"];
var eventsOutside = ["afterprint", "beforeprint", "filterchange", "help", "propertychange", "readystatechange"];
var events = eventsCommon.concat(eventsBody, eventsForm, eventsMarquee, eventsEdit, eventsData, eventsOutside);
for (var type = 0; type < events.length; type++) {
if ($('[el-' + events[type] + ']').length > 0) {
$(document).on(events[type], '[el-' + events[type] + ']', function (evt) {
var $target = $(evt.target);
var $currentTarget = $(evt.currentTarget);
var directiveStr = $currentTarget.attr('el-' + evt.type);
var directiveArray= directiveStr.split('&');
for(var dirIndex=0;dirIndex<directiveArray.length;dirIndex++)
{
var directive=directiveArray[dirIndex];
if (directive) {
var handler = '';
var args = [];
args.push(evt);
if ((directive.indexOf('(') !== -1) && (directive.indexOf(')') !== -1)) {
var directiveFun = directive.substring(0, directive.indexOf('('));
var directiveArgs = directive.substring(directive.indexOf('('));
var directiveNew = 'that._argsFactory' + directiveArgs;
handler = directiveFun;
var directiveArgs = eval('(' + directiveNew + ')');
if(handlers[handler])
{
handlers[handler].apply(evt.currentTarget, args.concat(directiveArgs));
}
}
else {
handler = directive;
if(handlers[handler])
{
handlers[handler].apply(evt.currentTarget, args);
}
}
}
}
});
}
}
}
_common.PageAbstract.prototype._argsFactory = function () {
var args = [];
for (var i = 0; i < arguments.length; i++) {
args.push(arguments[i]);
}
return args;
}
_common.PageAbstract.prototype.dispose = function () {
//如果实现了destroyDOM方法就执行
if (this.destroyDOM && (typeof this.destroyDOM == 'function')) {
this.destroyDOM();
}
}
//继承父类,父类中实现接口。(具体业务代码,接口的使用)
<script src="../resources/js/public/requirejs/require.js" data-main="../resources/js/controller/page/替换业务脚本"></script>
//使用requireJS定义js依赖
require.config({
paths: {
"jquery": "http://e.elong.com/resources/js/public/jquery/jquery-1.9.1",
"etiming": "../../../../../resources/js/elong/etiming",
"jqueryui": "http://e.elong.com/resources/js/public/jqueryui/jquery-ui-1.9.2",
"jquery.validate": "http://e.elong.com/resources/js/public/validate/jquery.validate",
"datetimepicker": "http://e.elong.com/resources/js/public/datetimepicker/jquery.datetimepicker",
"qtip2": "http://e.elong.com/resources/js/public/qtip2/qtip2",
"utility": "http://e.elong.com/resources/js/elong/utility",
"plugins": "http://e.elong.com/resources/js/elong/plugins",
"common": "http://e.elong.com/resources/js/elong/common",
"timingStatistics": "http://e.elong.com/resources/js/elong/timingStatistics",
"countlySDK": "http://e.elong.com/resources/js/elong/countlySDK",
"s_code": "http://www.elongstatic.com/common/js/noexpire/s_code.js?t=201401071938"
},
shim: {
"jqueryui": {
"deps": ["jquery"]
},
"jquery.validate": {
"deps": ["jquery"]
},
"datetimepicker": {
"deps": ["jquery"]
},
"qtip2": {
"deps": ["jquery"]
},
"utility": {
exports: "utility"
},
"plugins": {
"deps": ["jquery"]
},
"common": {
"deps": ["jquery"],
exports: "common"
},
"countlySDK": {
"deps": ["utility"],
exports: "countly"
},
"timingStatistics":{
"deps": ["jquery"],
"exports": "timingStatistics"
},
"s_code": {
}
}
});
//requireJS异步加载模块
require(["jquery",
"utility",
"countlySDK",
"common",
"timingStatistics",
"layout",
"jqueryui",
"jquery.validate",
"qtip2",
"plugins"], function ($, utility, countly, common,timingStatistics){
//ElementAdd构造函数。
var ElementAdd = function () {
//this指向ElementAdd实例,that方便在this指针改变指向的回调和内部方法中引用当前实例。
var that = this;
//ajax的url和href跳转地址依存的属性
this.action = {
test: '/bms-web-admin/admin/test?id=1'
};
//事件处理函数依存的属性
this.handler = {
nimei: function (evt) {
console.log(this);
console.log(arguments);
},
submitElement: function (evt) {
countly.recordEvent('createElement');
var $this = $(this);
evt.preventDefault();
if (BMSAdmin.config.frontend.isValidate) {
if (that.$form_elementAdd.valid()) {
that.$form_elementAdd.submit();
}
}
else {
that.$form_elementAdd[0].submit();
}
},
getTest: function (evt) {
countly.recordEvent('eventTest1');
var $this = $(this);
evt.preventDefault();
common.ajax({
url: that.action.test,
data: {'id': 12},
success: that.ajaxCallBack.renderCity,
error: that.ajaxCallBack.error
});
}
};
//ajax回调函数依存的属性。
this.ajaxCallBack = {
renderCity: function (data) {
},
error: function (err) {
}
};
//调用父类构造函数
ElementAdd.superclass.constructor.call(this);
};
//继承PageAbstract抽象类。必须定义action,handler,ajaxCallBack的公有属性。子类中必须实现initialize,initializeDOM,destroyDOM,render方法。
utility.inherits(ElementAdd, common.PageAbstract);
/**
* 初始化DOM函数,当前DOM中需要使用节点作为属性存储在实例中。
*/
ElementAdd.prototype.initializeDOM = function () {
this.$form_elementAdd = $('#form_elementAdd');
};
/**
* 初始化函数。
*/
ElementAdd.prototype.initialize = function () {
BMSAdmin.showBackendValidate(this.$form_elementAdd);
if (BMSAdmin.config.frontend.isValidate) {
this.$form_elementAdd.validate({
rules: {
name: {
required: true
},
element_key: {
isVariables: true,
minlength: 2,
maxlength: 25,
required: true
}
},
messages: {
name: {
required: '必填'
},
element_key: {
minlength: '最小长度2',
maxlength: '最大长度25',
required: 'element_key必填'
}
},
showErrors: function () {
var successList = this.successList;
var errorList = this.errorList;
for (var i = 0; errorList[i]; i++) {
var error = errorList[i];
common.showTips("#form_elementAdd", error.element, error.message);
}
for (var j = 0; successList[j]; j++) {
var success = successList[j];
common.showTips("#form_elementAdd", success, "");
}
},
success: $.noop
});
}
};
/**
* 渲染页面。
*/
ElementAdd.prototype.render = function () {
};
/**
* 销毁DOM。
*/
ElementAdd.prototype.destroyDOM = function () {
this.$form_elementAdd = null;
};
//公有方法
ElementAdd.prototype.myFunction1 = function () {
};
ElementAdd.prototype.myFunction2 = function () {
};