zoukankan      html  css  js  c++  java
  • YUI3组件框架之plugin

    plugin相关源码分析:

    plugin功能包括如下几个模块, 简单分析如下:

    pluginhost-base

    维护对象 this._plugins = {};

    并提供方法: plug、unplug、hasplug、_destroyPlugins、_initPlugins

    plug: 初始化插件实例,并与host进行关联   

    if (Plugin && !L.isFunction(Plugin)) {
        config = Plugin.cfg;
        Plugin = Plugin.fn;
    }
    
    // Plugin should be fn by now 
    if (Plugin && Plugin.NS) {
        ns = Plugin.NS;
    
        config = config || {};
        config.host = this;
    
        if (this.hasPlugin(ns)) {
            // Update config 
            if (this[ns].setAttrs) {
                this[ns].setAttrs(config);
            }
        } else {
            // Create new instance 
            this[ns] = new Plugin(config);
            this._plugins[ns] = Plugin;
        }
    }

    _initPlugins: 调用模块 pluginhost-config 中的_initConfigPlugins(config);

    • 根据this._classes(原型链上的constructor对象)上的静态属性 _PLUG and _UNPLUG, 来初始化plugin
    • 通过widget初始化时的config配置, 来初始化plugin
    • 在YUI Widget体系中base-core模块用来初始化插件, 初始化所有ext和ATTRS后调用  
    PluginHost.prototype.\_initConfigPlugins = function(config) {
    
        // Class Configuration
        var classes = (this._getClasses) ? this._getClasses() : [this.constructor],
            plug = [],
            unplug = {},
            constructor, i, classPlug, classUnplug, pluginClassName;
        // TODO: Room for optimization. Can we apply statically/unplug in same pass?
        for (i = classes.length - 1; i >= 0; i--) {
            constructor = classes[i];
    
            classUnplug = constructor._UNPLUG;
            if (classUnplug) {
                // subclasses over-write
                Y.mix(unplug, classUnplug, true);
            }
    
            classPlug = constructor._PLUG;
            if (classPlug) {
                // subclasses over-write
                Y.mix(plug, classPlug, true);
            }
        }
    
        for (pluginClassName in plug) {
            if (plug.hasOwnProperty(pluginClassName)) {
                if (!unplug[pluginClassName]) {
                    this.plug(plug[pluginClassName]);
                }
            }
        }
    
        // User Configuration
        if (config && config.plugins) {
            this.plug(config.plugins);
        }
    };  

    pluginhost-config

    • _initConfigPlugins
    • 静态方法: plug、unplug
    • 提供给Y.Base引用

    base-pluginhost

    mixin Base and PluginHost, 即:
    
    Y.mix(Base, PluginHost, false, null, 1);
    Base.plug = PluginHost.plug;
    Base.unplug = PluginHost.unplug;  

    plugin

    继承Y.Base . 提供AOP的一系列方法, 如:

    doBefore: function(strMethod, fn, context) {
        var host = this.get("host"), handle;
        if (strMethod in host) { // method
            handle = this.beforeHostMethod(strMethod, fn, context);
        } else if (host.on) { // event
            handle = this.onHostEvent(strMethod, fn, context);
        }
        return handle;
    },
    doAfter: function() {
        ...
    },
    onHostEvent: function() {
        var handle = this.get("host").on(type, fn, context || this);
        this._handles.push(handle);
        return handle;
    },
    afterHostEvent: function() {
        ...
    },
    beforeHostMethod: function() {
        ...
    },
    afterHostMethod: function() {
        ...
    } 

    如何写一个插件

    1、 任何简单对象即可成为一个简单插件, 如:

    function NodeDrag(config) {
        var host = config.host;
        drag(host);
    }
    function drag(host) {
        ...
    }

    2、YUI的Plugin基类提供了基于事件的AOP机制支持,可以通过继承它在不影响原有代码逻辑前提下,通过对代码执行过程的控制,达到改变原有代码逻辑或者增加插件功能的效果, 如:

    function NodeDrag() {
        NodeDrag.superclass.constructor.apply(this, arguments);
    }
    Y.extend(NodeDrag, Y.Plugin.Base, {
        drag: function() {
            ...
        }
    });

    使用插件的几种方式

    给一个node节点添加一个插件

    1、使用Base的静态方法, 实际调用的是pluginhost-config里面的plug方法

    Y.Base.plug(Y.one('#foo'), NodeDrag, config);

    2、node对象和继承了Y.Base对象的实例都可以通过实例直接调用plug方法使用插件

    Y.one('#foo').plug(NodeDrag, config);

    3、具体widget

    function Widget() {}
    Y.extend(Widget, Y.Base, {
        initializer: function() {
            ...
        }
    });
    var w = new Widget({plugins: NodeDrag});
    //var w = new Widget({plugins: [NodeDrag, ..]});
    //var w = new Widget({plugins: {fn: NodeDrag, cfg: {} });
    //w.plug(NodeDrag, cfg);
    

      

    在一些情况,为了让调用者不必过多的关心实现细节的时候,也将插件的初始化放到具体widget的实现中, 如:

    Widget.ATTRS = {
        drag: {
            value: false
        }
    };
    Y.extend(Widget, Y.Base, {
        initializer: function() {
            if(this.get('drag')) {
                this.plug(NodeDrag, cfg);
            }
        }
    });

    插件的一些优势和适合的场景

    • 插件一般是基于host开发的扩展功能, 用以对host功能的增强,如一些动画效果、也类如dota游戏中一些英雄所具有的各种技能等
    • 插件机制能对复杂功能进行更好的抽象, 减少代码逻辑的耦合
      • 如,在代码中由于加入一个功能,会涉及到很多代码片段加入if else 判断逻辑, 那么可以考虑将这个功能作为一个plugin增强, 使用AOP的方式与原来代码逻辑关联起来
    • 通过host进行统一的入口管理
  • 相关阅读:
    计算机网络技术基础2
    java基础
    跨页传递参数或临时表的几种方法
    ASP.NET2.0文件上传以及图片处理总结篇 [转]
    正则表达式
    ASP.NET2.0中WEB应用程序的部署
    比较著名的.net技术论坛名称
    WordPress 插件开发实例 – 详细注释的 Widget 开发例子
    Java Applet签名验证
    Java Logging API Tutorial
  • 原文地址:https://www.cnblogs.com/mininice/p/3876304.html
Copyright © 2011-2022 走看看