位置:首页 » 文章/教程分享 » 浅谈jQuery Easyui的继承和依赖原理

话说,大家都知道jQuery Easyui的各种组件之间是有继承或者依赖关系的,那么大家是否真的理解这里提到的“继承”或者“依赖”的关系了?本文就这两个问题做较为全面的阐述,希望通过本文大家能对easyui的运作机制有更为透彻的理解。继承和依赖关系主要体现在下面三点:

  • 属性的继承
  • 事件的继承
  • 方法的继承

属性的继承:

我们以combo和validatebox组件的关系作为例子,combo的属性继承自validatebox。我们先看combo组件构造函数的代码:

/**  
 * 1.3.2版本combo组件的构造函数  
 * @param {} options  
 * @param {} param  
 * @return {}  
 */  
$.fn.combo = function(options, param) {   
    if (typeof options == "string") {   
        return $.fn.combo.methods[options](this, param);   
    }   
    options = options || {};   
    return this.each(function() {   
        var state = $.data(this, "combo");   
        if (state) {   
            $.extend(state.options, options);   
        } else {   
            var r = _e(this);   
            state = $.data(this, "combo", {   
                //唯有此处有继承之嫌疑,可是丝毫看不出combo继承了validatebox什么属性啊,怎么回事呢。   
                options : $.extend({}, $.fn.combo.defaults,$.fn.combo.parseOptions(this), options),   
                combo : r.combo,   
                panel : r.panel,   
                previousValue : null  
            });   
            $(this).removeAttr("disabled");   
        }   
        //...   
    });   
};


acombo组件的代码里,我们没有捕捉到combo组件继承validatebox组件属性的地方,但是对于这句代码我们还没有深究:

options : $.extend({}, $.fn.combo.defaults,$.fn.combo.parseOptions(this), options) 
我们再来看看combo组件的属性解析器是如何定义的:

/**  
 * 看到了不?是不是心中暗喜,原来藏在这里。  
 * 我们看到combo组件的属性来自于以下几部分;  
 * 1.validatebox组件属性转换器转换解析dom获取到的属性(优先级最低);  
 * 2.公用属性转换器转换指定的几个属性(优先级次之);  
 * 3.写死的panelHeight,multiple,disabled,value(优先级最高)  
 * @param {} target  
 */  
$.fn.combo.parseOptions = function(target) {   
    var t = $(target);   
    return    
    $.extend(   
        {},    
        $.fn.validatebox.parseOptions(target),    
        $.parser.parseOptions(target,    
        ["width", "height", "separator",    
            {   
                panelWidth : "number",   
                editable : "boolean",   
                hasDownArrow : "boolean",   
                delay : "number"  
            }   
        ]),    
        {   
            panelHeight : (t.attr("panelHeight") == "auto"? "auto" : parseInt(t.attr("panelHeight")) || undefined),   
            multiple : (t.attr("multiple") ? true : undefined),   
            disabled : (t.attr("disabled") ? true : undefined),   
            value : (t.val() || undefined)   
        }   
    );   
}; 
综合combo的构造函数和combo的属性转换器,我们最终可以得到,combo的属性的属性来源,可以用简单的用下图来表示:


到这里为止,我们对jQuery Easyui组件之间属性的继承方式已经大致理解。其中重点是其继承方式是使用的jQuert的extend函数实现的,所以要想彻底明白,必须对extend函数有足够的了解,当然了这超出了本篇文章的讨论范围,请大家自行翻阅资料。

事件的继承:

在传统的面向对象语言中,事件这个概念并不存在jQuery Easyui的事件其实也就是属性,继承的原理跟属性的继承完全一样,只不过这个属性是个带有函数罢了,开发者可以定义这个函数。然而大多事件最终是通过javascript的call函数来触发的,我们那combo组件的onHidePanel事件来看:

function hiddenPanel(target){   
    var opts = $.data(target, "combo").options;   
    var panel = $.data(target, "combo").panel;   
    panel.panel("close");   
    //用户可以自定义opts.onHidePanel这个函数   
    //在combo的内部方法中会在程序中的适当位置调用这个函数,并且将上下文设置为target   
    opts.onHidePanel.call(target);   
} 

方法的继承:

跟传统面向对象的语言一样,jQuery Easyui组件间的方法也是可以继承的,那么方法又是怎样被继承的呢,我们拿combobox组件的构造函数来分析:

$.fn.combobox = function(options, params){   
    //如果构造函数第一个入参是字符串,则是方法调用。   
    if (typeof options == "string") {   
        //尝试到combobox组件中找这个方法   
        var caller = $.fn.combobox.methods[options];   
        if (caller) {   
            //如果找到了这个方法,则调用之   
            return caller(this, params);   
        }   
        else {   
            //如果没有找到,则调用combo组件的同名方法   
            return this.combo(options, params);   
        }   
    }   
    //...   
};  

官方的API里面说,combobox组件的方法集成自combo组件,这个在combobox组件的构造函数中已经充分体现出来了,jQuery Easyui所谓的继承,只不过是它内部的一种实现方案,并不是真正意义上的“继承”。

同时我们还必须看到方法继承的特殊性,即对用承载combobox组件的target,肯定也承载了combo组件,要不然不可能调用combo组件的方法,所以combobox组件的初始化过程中一定也在target上初始化了combo组件,也就是说,在target上肯定同时存储了名为"combo"和"combobox"的对象:

$.data(target,'combobox')//能取到数据   
$.data(target,'combo')//也能取到数据  

这就好比combo是个汽车人里的“大黄蜂”的汽车状态,那么combobox绝对不是由若干汽车人组成的超级擎天柱,而仅仅是由“汽车状态”变成了“机器人”状态的大黄蜂,换汤不换药,这是方法能够继承的前提。

依赖涵盖继承:

依赖关系不仅仅体现在“继承”上面,也现成在“组成”上面,所以个人概括地用“依赖” == “继承” + “组成”;这个表达式来表示有依赖关系的组件。

我们拿dialog,window,linkbutton三个组件的关系来举例说明:

dialog组件依赖window组件和linkbutton组件。dialog其实就是window,因为他们有方法上的继承;同时window内部有实例化了linkbutton组件。这就好比,“汽车态”的大黄蜂变成了“机器人”状态的大黄蜂,同时一条吉娃娃跳到了它的手掌心,这只吉娃娃就是linkbutton了。