基于YUI3的方法链式调用

yui3.0.0beta终于千呼万唤使出来,鼓掌!!!下载在这里:http://developer.yahoo.com/yui/3/

说到js的方法链式调用,的确,jquery确实给了wd们很多美好的回忆;所谓链式调用是一种语法上的小hack,也仅仅停留在代码级别,不过这种方法确实能使工程师用少量的代码达到复杂的操作目的,是一种很值得推广的技巧。不过yui2在这方面没作多少工作,yui3开始大量的使用这种技巧,让人猛然感觉语法风格和yui2的迥异。

在yui2中,我要对某个dom元素执行一系列的操作必须要这样:

var el = YAHOO.util.Dom.get(‘id’);
YAHOO.util.Dom.addClass(el,’className’);
YAHOO.util.Dom.setStyle(el,’display’,'block’);

在yui3中可以这样:

Y.get(‘#id’).addClass(‘className’).setStyle(‘display’,'block’);

语法上简洁了很多,这种写法就是所谓的链式调用。yui3的链式调用如何实现的、扩展行好不好呢?上篇介绍yui3的装饰者的时候涉及到一点这方面的内容:方法的声明+定义。比如,要对dom节点扩展一个fuck行为,则需要:

Y.mix(Y.DOM,{
    fuck:function(o){
        alert(o.innerHTML);//定义
    }
});
Y.Node.addDOMMethods([
    'fuck'//声明
]);

为什么不直接定义,而要加一个“声明“出来,这种做法是为了降低库模块之间的耦合,即我在定义这个fuck的时候不必知晓DOM内部的逻辑,DOM 在调用fuck的时候则会自动返回一个包装好的Node,这种做法增加了库的可扩展性。再来看一个例子,我要模拟一个‘人’的行为,分别用yui3和不用库来作,看两者的区别,基于yui3:

YUI().use(‘node’, function(Y){
    Y.mix(Y.DOM,{
        eat:function(o){
            o.innerHTML += ‘吃!’;
        },
        drink:function(o){
            o.innerHTML += ‘喝!’;
        },
        shit:function(o){
            o.innerHTML += ‘拉!’;
        },
        pee:function(o){
            o.innerHTML += ‘撒!’;
        },
        fuck:function(o){
            o.innerHTML += ‘o!’;
        }
    });

    Y.Node.addDOMMethods(['eat','drink','shit','pee','fuck']);

    //runtime
    Y.get(‘#aperson’).eat().drink().shit().pee().fuck();
});

“Y.get(’#aperson’).eat().drink().shit().pee().fuck()“这句即是这个person一溜烟的执行了吃喝拉撒干的动作,连隔都不带打的。

在来看看不用任何库作的方法链式调用:

var $ = function(id){
    var _$ = function(id){
        this.el = document.getElementById(id);
    };
    _$.prototype.eat = function(){
        this.el.innerHTML+=’吃!’;
        return this;
    };
    _$.prototype.drink= function(){
        this.el.innerHTML+=’喝!’;
        return this;
    };
    _$.prototype.shit = function(){
        this.el.innerHTML+=’拉!’;
        return this;
    };
    _$.prototype.pee = function(){
        this.el.innerHTML+=’撒!’;
        return this;
    };
    _$.prototype.fuck = function(){
        this.el.innerHTML+=’o!’;
        return this;
    };
    return new _$(id);
};

//runtime
$(‘aperson’).eat().drink().shit().pee().fuck();

这里的$(’aperson’).eat().drink().shit().pee().fuck()也是一溜烟的吃喝拉撒睡,但在实现具体方法的时候,每个方法都要return this,而真正灵活的扩展则不希望这样作。在js库流行的今天,这种降低耦合增加扩展性的小技巧显的尤为重要。

posted at