2019独角兽企业重金招聘Python工程师标准>>>

前几天一个工作需要,写了一个jquery的小插件,想起来这篇让我受益匪浅的老文章,翻译出来给大家看看。这是我翻译的第一篇文章,如果觉得实在太差,看不下去了,请移步原文: http://www.learningjquery.com/2007/10/a-plugin-development-pattern 。真的是好文一篇! ----------------------------------我只是分割线------------------------------------------ 我开发jQuery插件已经有一段时间了,这个过程中我形成了一个很舒服的插件开发风格。这篇文章我就介绍一下我发现的这个对插件开发很有帮助的模式。这里我假设你对jQuery插件的开发已经有一个基本的理解了。如果你还是个新手,建议你先看一下 jQuery Authoring Guidelines 这里列举一些我认为这个模式做得好的点(requirements)

  1. 在jQuery的命名空间中声明一个简单(唯一)的名字

  2. 接收一些可选的参数来控制插件的行为

  3. 提供对插件默认配置的访问方法

  4. 提供对辅助功能的访问方法

  5. 保持私有方法是私有的

  6. 支持插件元数据(the Metadata Plugin)

下面我将对上面这些点逐一解释,并且按照他们实现一个文本高亮的小插件。

在jQuery的命名空间中声明一个简单(唯一)的名字

这句话的隐含意思是:单一插件的脚本(a  single-plugin script),假如你的脚本中包含多个插件,或者一对功能对称的插件(比如$.fn.doSomething() 和 $.fn.undoSomething() ),那么你应该声明多个名字。一般情况下。我们开发插件的时候,都力求做到能用一个简单的名字来包含/表达插件所有的功能细节。 在我们接下来的这个例子中,我们就用“hilight”这个名字。

// plugin definition
$.fn.hilight = function() {// Our plugin implementation code goes here.
};

然后,可以这样调用我们的插件:

$('#myDiv').hilight();

如果要将我们的实现拆成多个函数该怎么办呢?我们有足够的理由要拆成多个函数,比如:设计的需要啊;代码可读性的需要啊;为了符合OO语义的需要啊;等等。 将实现拆分成多个函数且不污染jQuery的命名空间其实挺微琐碎的一件事儿。我们借着“在JavaScript中,function就是一级对象”的特性有意识的来做到这点。和其他对象一样,function也可以有自己的属性。我们刚刚已经在jQuery的原型对象上声明了一个“hilight”。然后任何需要被暴露的属性和方法我们都可以作为hilight函数的属性声明出来。这个等会儿还会作详细解释。

接收一些可选的参数来控制插件的行为

我们给hilight插件加上指定特定前景色和背景色的功能。我们需要允许向插件函数传递一个配置对象来进行配置。比如这样:

// plugin definition
$.fn.hilight = function(options) {var defaults = {foreground: 'red',background: 'yellow'};// Extend our default options with those provided.var opts = $.extend(defaults, options);// Our plugin implementation code goes here.
};

现在我们的插件就可以这样调用了。

$('#myDiv').hilight({foreground: 'blue'
});

提供对插件默认配置的访问方法

我们可以(应该)将插件的默认配置用下面的方法暴露出去。这很重要,因为这可以让插件的使用者用很容易用很少的代码来覆盖/自定义插件。然后这里我们就利用到了function对象作为“一级对象”的便利特性。

// plugin definition
$.fn.hilight = function(options) {// Extend our default options with those provided.// Note that the first arg to extend is an empty object -// this is to keep from overriding our "defaults" object.var opts = $.extend({}, $.fn.hilight.defaults, options);// Our plugin implementation code goes here.
};
// plugin defaults - added as a property on our plugin function
$.fn.hilight.defaults = {foreground: 'red',background: 'yellow'
};

现在,用户就可以在他们的代码中写这么一行:

// this need only be called once and does not
// have to be called from within a 'ready' block
$.fn.hilight.defaults.foreground = 'blue';

然后依然用这种方法调用我们的插件,就可以用蓝色做为前景色了

$('#myDiv').hilight();

正如你所见,用户可以像这样写一行简单的代码就能改变插件默认的前景色。而且用户仍然可以选择覆盖这个新的默认值:

// override plugin default foreground color
$.fn.hilight.defaults.foreground = 'blue';
// ...
// invoke plugin using new defaults
$('.hilightDiv').hilight();
// ...
// override default by passing options to plugin method
$('#green').hilight({foreground: 'green'
});

提供对辅助功能的访问方法

这一条和前面几条是紧密相连的,是一个扩展你的插件的有趣的方式(包括让别人来扩展你的插件)。例如,我们的实现中可能包含一个叫format的方法来对要高亮的文本进行格式化。这时我们的插件看起来是这样的,我们在hilight方法下面提供了一个format方法的默认实现。

// plugin definition
$.fn.hilight = function(options) {// iterate and reformat each matched elementreturn this.each(function() {var $this = $(this);// ...var markup = $this.html();// call our format functionmarkup = $.fn.hilight.format(markup);$this.html(markup);});
};
// define our format function
$.fn.hilight.format = function(txt) {'return '<strong>' + txt + '</strong>';
};

我们也可以简单的在配置对象中提供一个属性来作为回调函数来达到覆盖默认的格式化。这是另一种让你的插件支持可定制化的好方法。这里展示的是进一步的将format方法暴露出去,让别人可以对他进行重新定义。通过这种技术,别人可以将他们自己对你的插件的修改提供给其他人用,换句话说,就是能让别人给你的插件写插件。 在我们这篇文章中介绍的这个小插件中,你可能认为这没什么用。有一个真实的例子是  Cycle Plugin,Cycle Plugin是一个提供了很多内置动画效果(滚动,滑动,淡入淡出)的幻灯片插件。但是事实上,他没有提供一种实现简单的幻灯片切换效果的途径。那,这里就是上面这种扩展方式非常有用的地方了。Cycle Plugin就暴露了一个叫“transitions”的对象,让用户可以自己定义幻灯片的切换效果。在他插件代码里就是这样写的:

$.fn.cycle.transitions = {// ...
};

这种技术就让其他人为Cycle Plugin编写幻灯片切换效果成为可能了。

保持私有函数私有

将你的插件部分功能暴露出去让他们可以被覆盖是一个很强大的技术。但是你需要想清楚,你的哪部分实现是需要暴露出去的。一旦你暴露出去了,就要时刻提醒自己:对这个函数的调用参数和语义做任何修改都可能破坏他的向后兼容性。一般的规则是,如果你不确定这个函数该不该被暴露出去,那就不要暴露出去。 那么我如何在既不污染命名空间又不将函数暴露出去的情况下添加更多的函数呢?这就是闭包(closures)干的事儿。为了演示,我们在插件里再添加一个叫“debug”的函数。debug函数将在FireBug的控制台上记录被选择的元素的数量。为了建立一个闭包,我们将整个插件的定义包起来(详见  jQuery Authoring Guidelines)。

// create closure
(function($) {// plugin definition$.fn.hilight = function(options) {debug(this);// ...};// private function for debuggingfunction debug($obj) {if (window.console && window.console.log)window.console.log('hilight selection count: ' + $obj.size());};//  ...
// end of closure
})(jQuery);

这样debug方法不能被闭包外面的代码所访问到,所以,它就是我们插件私有的了。

支持插件元数据

根据你写的插件的类型,提供对元数据的支持,可以让它变得更加强大。我个人喜欢它的原因是因为它可以让你用不那么扎眼的html标签就能修改插件的默认配置(这点在写示例的时候非常有用)。而且实现起来也很简单!

// plugin definition
$.fn.hilight = function(options) {// ...// build main options before element iterationvar opts = $.extend({}, $.fn.hilight.defaults, options);return this.each(function() {var $this = $(this);// build element specific optionsvar o = $.meta ? $.extend({}, opts, $this.data()) : opts;//...

改变的这行做了下面这些事儿:

  • 检查是否安装了元数据

  • 如果安装了,用安装的元数据扩展我们的配置对象

让元数据作为jQuery.extend方法的最后一个参数,保证前面的配置一定会被它覆盖。现在,我们可以选择用标签来驱动插件的行为了。

<!--  markup  -->
<div class="hilight { background: 'red', foreground: 'white' }">Have a nice day!
</div>
<div class="hilight { foreground: 'orange' }">Have a nice day!
</div>
<div class="hilight { background: 'green' }">Have a nice day!
</div>

然后现在我们可以用一行代码就可以让每个div拥有不同的行为了。

$('.hilight').hilight();

来个总结

下面是我们这个例子的完整代码:

//
// create closure
//
(function($) {//// plugin definition//$.fn.hilight = function(options) {debug(this);// build main options before element iterationvar opts = $.extend({}, $.fn.hilight.defaults, options);// iterate and reformat each matched elementreturn this.each(function() {$this = $(this);// build element specific optionsvar o = $.meta ? $.extend({}, opts, $this.data()) : opts;// update element styles$this.css({backgroundColor: o.background,color: o.foreground});var markup = $this.html();// call our format functionmarkup = $.fn.hilight.format(markup);$this.html(markup);});};//// private function for debugging//function debug($obj) {if (window.console && window.console.log)window.console.log('hilight selection count: ' + $obj.size());};//// define and expose our format function//$.fn.hilight.format = function(txt) {return '<strong>' + txt + '</strong>';};//// plugin defaults//$.fn.hilight.defaults = {foreground: 'red',background: 'yellow'};
//
// end of closure
//
})(jQuery);

这个设计模式,让我能够开发出更加强大,结构更加一致的插件。希望它对你也有同样的效果。

转载于:https://my.oschina.net/laichendong/blog/283808

(jQuery)插件开发模式相关推荐

  1. jQuery: 插件开发模式详解 $.extend(), $.fn, $.widget()

    原文:http://www.codeceo.com/article/jquery-plugin-develop.html 软件开发过程中是需要一定的设计模式来指导开发的,有了模式,我们就能更好地组织我 ...

  2. 【转载】jQuery插件开发精品教程,让你的jQuery提升一个台阶

    jQuery插件开发精品教程,让你的jQuery提升一个台阶 要说jQuery 最成功的地方,我认为是它的可扩展性吸引了众多开发者为其开发插件,从而建立起了一个生态系统.这好比大公司们争相做平台一样, ...

  3. jQuery插件开发教程

    jQuery插件开发精品教程,让你的jQuery提升一个台阶 要说jQuery 最成功的地方,我认为是它的可扩展性吸引了众多开发者为其开发插件,从而建立起了一个生态系统.这好比大公司们争相做平台一样, ...

  4. jquery插件开发导读

    最近发现项目中有些js代码可以重用,但是不知道怎么样组织,在网上调研后,发现jquery插件是一种很好的组织方式,而且项目也采用了jquery框架,所以花了点时间学习jquery插件开发,并且动手将部 ...

  5. jQuery插件开发 - 其实很简单

    [前言] jQuery已经被广泛使用,凭借其简洁的API,对DOM强大的操控性,易扩展性越来越受到web开发人员的喜爱,我在社区也发布了很多的jQuery插件,经常有人询问一些技巧,因此干脆写这么一篇 ...

  6. jquery 插件开发的作用域及基础

    2019独角兽企业重金招聘Python工程师标准>>> 之前一直有开发jquery插件的冲动,所以一直想学习如何进行插件开发,最近一个项目需要使用图片上传组件及自动无限下拉组件,百度 ...

  7. jQuery插件开发学习笔记

    今天想了解一下jQuery的插件开发,于是google了一下,列在前面的两篇文章都很不错,jQuery插件开发全解析 更是将插件开发的方方面面细致入微的进行了讲解,并提供了PDF进行下载.笔者今天详细 ...

  8. jQuery插件开发(一):jQuery类方法

    一.jQuery插件开发的方法 jQuery插件的编写方法主要有两种: 1.基于jQuery对象的插件 2.基于jQuery类的插件 二.基于jQuery类的插件 1.什么是jQuery类的插件? j ...

  9. jQuery插件开发的两种方法及$.fn.extend的详解

    2019独角兽企业重金招聘Python工程师标准>>> 作者: 字体:[增加 减小] 类型:转载 时间:2014-01-16 我要评论 jQuery插件开发分为两种:1 类级别.2 ...

  10. jQuery插件开发中$.extend和$.fn.extend辨析

    jQuery插件开发分为两种:   1 类级别 类级别你可以理解为拓展jquery类,最明显的例子是$.ajax(...),相当于静态方法. 开发扩展其方法时使用$.extend方法,即jQuery. ...

最新文章

  1. intellij远程调试_IntelliJ中的远程调试Wildfly应用程序
  2. vue js 和原生app调用回调方法问题
  3. 漫步最优化八——梯度信息
  4. php基础教程(二):基础语法
  5. RabbitMQ consumer的一些坑
  6. 贪心算法之加勒比海盗问题
  7. ymPrompt.js消息提示组件 详解 .
  8. 网站安全之存储型跨站脚本编制
  9. Python数据分析中Groupby用法之通过字典或Series进行分组
  10. Nsight中给工程添加include目录
  11. 有生成的日志的监控电脑性能的软件吗_全链路监控:方案概述与对比,看完你就懂...
  12. java商城的面试题,Java商城系统面试题(一)
  13. 使用 npm shrinkwrap 来管理项目依赖
  14. vue 监听输入法方法(js)
  15. BC1.2协议之SDP
  16. MLY翻译 -- 3.Prerequisites and Notation
  17. STM32H743使用PA0,PA1作为ADC输入的坑!!
  18. Python 自动化教程(5) : 自动生成Word文件
  19. mysql语言中子查询是什么_SQL查询语句中,什么叫子查询?
  20. LTE学习笔记之无线资源管理

热门文章

  1. 用vue-wechat-title为微信动态设置标题
  2. ubuntu常见问题有效解决办法
  3. 一个Lumen多层拆分手记
  4. Angular4记账webApp练手项目之四(在Angular4项目中用echarts绘制图表)
  5. bzoj1651: [Usaco2006 Feb]Stall Reservations 专用牛棚
  6. 设计模式学习笔记(二十:享元模式)
  7. RecyclerView,ListView,GridView等UI控件使用及其优化和图片错位--
  8. pycharm 修改新建文件时的头部模板(默认为__author__='...')
  9. lucene.net 3.0.3、结合盘古分词进行搜索的小例子(转)
  10. PHP User Agent