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进行统一的入口管理

YUI3组件框架之plugin的更多相关文章

  1. LCLFramework框架之Plugin模式

    插件应用架构概述 基于LCLFramework插件框架的应用由以下三个部分构成: (1)主程序:针对特定应用环境(Web.WinForm等应用环境),加载启动插件,获取插件入口,运行入口程序. (2) ...

  2. 利用 Dijit 组件框架打造丰富的用户界面

    原文出处:Joe Lennon 从头开始学习 Dojo,第 3 部分 利用 Dijit 组件框架打造丰富的用户界面 Dijit 是什么? Dijit 是 Dojo 工具包的富组件用户界面库.这些组件完 ...

  3. VUE- iView组件框架的使用

    VUE- iView组件框架的使用 1. 下载iView 工程. 引用:https://www.iviewui.com/

  4. 【原】从一个bug浅谈YUI3组件的资源加载

    篇前声明:为了不涉及业务细节,篇内信息统一以某游戏,某功能代替 前不久,某游戏准备内测客户端,开发人员测试过程中发现某功能突然不灵了,之前的测试一切ok,没有发现任何异常,第一反应是,游戏内浏览器都是 ...

  5. 腾讯发布新版前端组件框架 Omi,全面拥抱 Web Components

    Omi - 合一 下一代 Web 框架,去万物糟粕,合精华为一 → https://github.com/Tencent/omi 特性 4KB 的代码尺寸,比小更小 顺势而为,顺从浏览器的发展和 AP ...

  6. Yii2 Template 组件框架集封装

    项目简介: Yii2_Template是一个“提供大多数PHP常用的组件去集合成的一套基于Yii2的项目框架”. 该项目是一款秉着提高 开发效率.降低开发成本,遵循高拓展,高可用的原则的进行开发的框架 ...

  7. stenciljs ionic 团队开发的方便web 组件框架

    stenciljs 是ionic 团队开发的方便组件话开发的js 框架,具体以下特点 简单,零配置,简单的api,typescript 支持 性能,压缩之后6Kb,支持ssr,以及强大的原生web c ...

  8. Vue的iview组件框架select远程搜索,选中后不刷新的问题

    1.场景:弹框内有一个下拉组件(支持搜索),当选择完数据后弹框关闭,再次打开后,下拉框内的数据是刚才选中的数据.原因:分析后觉得是搜索内容没有清空,导致下拉的数据只有一个 2.解决方案 a .解决:调 ...

  9. React 组件框架

随机推荐

  1. BLE抓包是怎么回事儿?

    BLE抓包 在进行网络开发的时候,抓包是一个很重要的调试过程,通过抓包可以分析网络传输的数据是否正确,可以深入理解网络传输过程.在物联网开发中,BLE低功耗蓝牙技术是一种非常通用的网络传输方式.在学习 ...

  2. SQL基础学习_03_数据更新

    数据的插入 1. 基本INSERT语句     INSERT的基本语法为:     INSERT INTO  <表名> (列1, 列2, 列3,  -) VALUES (值1, 值2, 值 ...

  3. Swift3中数组创建方法

    转载自:http://blog.csdn.net/bwf_erg/article/details/70858865 数组是由一组类型相同的元素构成的有序数据集合.数组中的集合元素是有 序的,而且可以重 ...

  4. CSS样式表学习

    ---恢复内容开始--- 今天学习的主要内容是样式表和选择器. 1.样式表的分类 1.内联式样式表 特点:能实现精确控制,但是范围太小.页面显示的优先级高于其他样式表 2.内嵌式样式表 特点:必须在h ...

  5. TurnipBit之DIY无线遥控智能小车

    一.准备工作 TurnipBit 开发板 2块 TurnipBit 扩展板 1块 数据线 1条 智能小车器件 1套 电机驱动模块(L298N) 1个 在线可视化编程 点击进入   二.思路设计   2 ...

  6. 【漏洞分析】dedecms有前提前台任意用户密码修改

     0x00 前言 早上浏览sec-news,发现锦行信息安全发布了一篇文章<[漏洞分析] 织梦前台任意用户密码修改>,看完之后就想着自己复现一下. 该漏洞的精髓是php的弱类型比较,'0. ...

  7. 设计模式(三)装饰者模式Decorator

    装饰者模式针对的问题是:对一个结构已经确定的类,在不改变该类的结构的情况下,动态增加一些功能. 一般来说,都是对一些已经写好的架构增加自己的功能,或者应对多种情况,增加功能. 我们还是来玩一句红警,首 ...

  8. Hadoop 新生报道(四) WordCount

         WordCount是hadoop里hello word级的第一个程序,作为一个萌新,我也来跑一跑这个,附带针对新人的说明.      所谓WordCount,就是统计一个或几个文档中相同的单 ...

  9. TypeScript体验

    TypeScript 在线玩 http://www.typescriptlang.org/play/index.html ts最终编译成js  网站最终还是要引用js.  ts面向对象的感念更加直观, ...

  10. 自己写的驱动用CreateFile打开时错误码返回1的问题

    就像题目上说的,今天在写一个例子代码时遇到了这个问题,下面是当时驱动层和应用层的代码: #include <ntddk.h> #define BASE_CODE 0x800 #define ...