`
houfeng0923
  • 浏览: 142676 次
  • 性别: Icon_minigender_1
  • 来自: 大连
社区版块
存档分类
最新评论

YUI3学习(八)---组件框架之 Plugin

阅读更多

 

 

插件可以让你无侵入地为衍生自Base类的宿主对象(称为host的对象)添加对象。如Node、Widget等类的对象实例。

可以通过继承Plugin.Base类来创建插件类。除此之外还可以通过后面的其他方法创建插件。

在Base类中已经介绍可以通过插件向组件实例添加功能,组件类甚至可以对插件功能一无所知。这样我们就可以在组件实例级别使用这些功能,

从而避免了为了添加这些功能而把组件类构造得很大或者构建多个不同的组件类。

 

1创建简单插件

对于简单的插件,如果不需要定义自己的事件和属性、不需要监听宿主的事件来改变宿主的行为、不需要重写宿主的方法的话,插件类可以只是简单的JavaScript类。

插件类唯一需要的是添加用作名称空间的静态属性“NS”,作为通过宿主实例对象来访问插件实例。

 

当插件被插入到宿主实例中后,插件实例就会被创建。宿主实例引用会作为参数传入到插件的构造器中,这样插件实例就可以获取宿主对象的引用。

当插件从宿主对象中拔出后,插件实例就被销毁。

 

//这个AnchorPlugin插件被设计成Node实例的插件 (宿主是Node实例)
function AnchorPlugin(config) {  
    // 存放宿主实例(Node实例)的引用,以便插件的其他方法使用。
    this._node = config.host;
}  
  
// 被插入到Node实例后,通过Node实例的"anchors"属性可以访问到插件
AnchorPlugin.NS = "anchors"  
  
AnchorPlugin.prototype = {  
    disable: function() {
        var node = this._node;//引用的宿主对象
        var anchors = node.all("a");
        anchors.addClass("disabled");
        anchors.setAttribute("disabled", true);
    }  
};
//为Node实例增加插件功能
var container = Y.one("div.actions");
container.plug(AnchorPlugin);
//根据插件NS属性的值,可以通过Node实例访问插件实例
container.anchors.disable();

  YUI框架中的插件,如Y.Plugin.Drop,Y.Plugin.NodeFX等,并不是需要提供监听和方法注入的功能,在实现中,只是extend Y.DD.DropY.Anim.具体可参考其源代码。
 对于需要在原始对象已有方法上扩展新的功能(如在widget调用hide时,增加动画效果插件)则需要利用下面介绍的Plugin.Base的生命周期管理和host方法注入功能。

 

2高级插件类

上述简单插件类可以满足简单的功能。但是当你想在插件类中实现更复杂的功能时,插件类如果支持attributes和events的能力就会非常的有用。

更重要的是,对于很多插件来说要修改宿主实例的默认行为。(比如一个Animation插件需要修改Widget类的show/hide行为)

对于这些需要丰富功能的插件,需要继承插件的基类Plugin.Base。

Plugin.Base是Base的子类,一次也支持attribute属性维护、生命周期方法及自定义事件。此外,我们可以在插件类中监听宿主实例触发的事件,或者在宿主某个方法执行

前/后,注入插件的自定义逻辑代码(基于YUI3的AOP基础结构)。Plugin.Base还定义了host属性,可以在插件中调用this.get(’host')获取宿主实例引用。

 

2.1扩展Plugin.Base

继承Plugin.Base可以像继承Base一样,需要注意的一点是,与简单插件相比,继承字Plugin.Base的插件,宿主实例会自动设置为插件的host属性。而简单的插件需要手动通过构造器将宿主实例传入插件实例并设置为属性才能访问。

继承自Plugin.Base的插件与继承自Base的子类是一样的,只不过是多个静态属性NS

 //一个为Widget的show/hide方法设置的动画插件
    function WidgetAnimPlugin(config) {  
        WidgetAnimPlugin.superclass.constructor.apply(this, arguments);  
    }
    //定义NAME和NS静态属性
    WidgetAnimPlugin.NAME = 'widgetAnimPlugin';  
    WidgetAnimPlugin.NS = 'fx';
    //为插件定义自定义属性
    WidgetAnimPlugin.ATTRS = {
        animHidden : {  
            ...
        },
        animVisible: {  
            ...  
        }
    };
    // 继承 Plugin.Base
    Y.extend(WidgetAnimPlugin, Y.Plugin.Base, {
        // 添加需要的原型方法
    });

 

YUI3为我们提供 了插件模版文件,我们可以使用它作为创建Plugin.Base类的良好的开始。

 

2.2Plugin的监听器

扩展Plugin.Base类最大的好处是可以使用Plugin.Base提供的onHostEventafterHostEvent方法来改变宿主实例事件触发时的行为,

还可以通过beforeHostMethodafterHostMethod方法来改变宿主实例的方法。 (此外Plugin.Base还提供了doBeforedoAfter方法,既可以监听事件,又可以改变方法。)

通过Plugin.Base类提供的这些方法来改变宿主实例默认行为,而不是通过修改宿主类来实现的好处是:通过插入的方式修改了对象方法在

拔出以后,对象方法会被还原。

 

事件

上面提到过,对于继承自Plugin.Base类的插件,可以监听宿主对象的事件,修改它们的行为。

比如,当widget被渲染的时候会触发render事件,插件可能需要知道这个事件什么时候发生,可以在宿主渲染的时候插入一些自定义的html片段。这就可以使用afterHostEvent方法来实现:

 

// 一个为widget创建圆角边框的插件
function RoundedCornersPlugin(config) {
    //...
}
RoundedCornersPlugin.NAME = 'roundedCornersPlugin';
RoundedCornersPlugin.NS = 'corners';
Y.extend(RoundedCornersPlugin, Y.Plugin.Base, {
    // 该方法会在Base的构造器方法中自动调用
    initializer: function(config) { 
         // "render" 是widget的事件
        this.afterHostEvent('render', this.insertCornerElements);
    },

    insertCornerElements: function() {
        var widget = this.get("host");
        var boundingBox = widget.get("boundingBox");
        var tl = Y.Node.create(TL_TEMPLATE);
        //...
        boundingBox.appendChild(tlNode);
        boundingBox.appendChild(trNode);
        boundingBox.appendChild(blNode);
        boundingBox.appendChild(brNode);
    }
});

 

 

 

方法

在某些情况下,插件需要覆盖宿主实例的一些方法。Plugin.Base提供的beforeHostMethod和afterHostMethod方法可以在宿主实例方法执行前后插入自定义的逻辑代码。

比如,为Widget实例的show和hide方法添加动画,可以通过覆盖控制widget boundingBox容器visibility样式的方法,添加修改透明度的动画来实现。

 

//一个为Widget的show/hide方法设置的动画插件
function WidgetAnimPlugin(config) {  
    //...  
}
WidgetAnimPlugin.NAME = 'widgetAnimPlugin';  
WidgetAnimPlugin.NS = 'fx';  

WidgetAnimPlugin.ATTRS = {
    animHidden : {
        //...  
    },
    animVisible: {  
        //...  
    }  
};  
  
// 扩展Plugin.Base 重载默认的改变显示状态的方法_uiSetVisible 。
Y.extend(WidgetAnimPlugin, Y.Plugin.Base, {
    initializer : function(config) {
        // 在_uiSetVisible调用前调用_uiAnimSetVisible方法
        this.beforeHostMethod("_uiSetVisible", this._uiAnimSetVisible);
    },
    _uiAnimSetVisible : function(show) {
        if (this.get("host").get("rendered")) {  
            if (show) {  
                this.get("animHidden").stop();  
                this.get("animVisible").run();  
            } else {  
                this.get("animVisible").stop();  
                this.get("animHidden").run();
            }
            // 阻止默认方法执行。  
            return new Y.Do.Prevent(‘AnimPlugin prevented default show/hide’);
        }  
    }  
});

 

 

关于完整的 WidgetAnimPlugin例子,请访问YUI Plugin官方例子

 

 

 

 

 

 

 

 

 

 

 

 

 

1
1
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics