jQuery 插件的模块化
jQuery 插件非常丰富。在传统使用方式里,比如 jquery-fancybox, 我们需要在页面中显式引入:
<script src="/js/jquery.min.js"></script> <script src="/js/jquery.easing-1.3.pack.js"></script> <script src="/js/jquery.mousewheel-3.0.4.pack.js"></script> <script src="/js/jquery.fancybox-1.3.4.js"></script> <link rel="stylesheet" href="/js/jquery.fancybox-1.3.4.css"/>
fancybox 依赖 easing 和 mousewheel, 因此还引入了这两个插件文件。当使用的插件越多,依赖关系越复杂时,上面的 script 列表会越难维护。
模块化
我们看下在 seajs 里如何做。
看 demo: FancyBox 1.3.4 | Demonstration
页面源码里,引入的 script 只剩下一处:
<script src="http://seajs.org/dist/sea.js" data-main="./init"></script>
来看 init.js:
/* init.js */ define(function(require) { var $ = require('jquery'); require('./fancybox/jquery.fancybox-1.3.4.js')($); // snip... });
init 依赖 jquery 和 fancybox, 因此 require 了这两个模块。
require('./fancybox/jquery.fancybox-1.3.4.js')
返回的是 function
, 其代码为:
/* jquery-fancybox-1.3.4.js */ define(function(require) { return function($) { require('./jquery.easing.1.3.js')($); require('./jquery.mousewheel.js')($); require('./jquery.fancybox-1.3.4.css'); // snip... }});
jQuery 插件的机制是往 $ 或 $.fn 上添加插件成员。在 seajs 里,我们可以将插件包装成一个函数。这样,在使用时,传入需要被扩展的 jQuery 实例就好。
对于不依赖其它插件的 jquery 插件,模块化包装就更简单了:
/* jquery.mousewheel.js */ define(function() { return function($) { // snip.. }});
通过这种方式,我们可以将任何 jquery 插件封装成 seajs 的模块!
共享模式
上面的方式可以概括为:
var $ = require('jquery'); require('some-jquery-plugin')($);
这是一种共享模式,一旦添加某个插件功能到 jQuery
后,其他模块里,require('jquery')
返回的 jquery 对象会自动拥有已经添加过的插件功能。这种共享模式可以对 jquery 的插件进行集中管理。比如对于具体项目,可以在 init.js 文件里:
/* init.js */ define(function(require) { var $ = require('jquery'); require('jq-plugin-a')($); require('jq-plugin-b')($); require('jq-plugin-c')($); // snip... });
这样,在其它模块中,通过 require('jquery')
就可以得到添加过所需要的所有插件功能的 jquery 对象。
子类模式
当项目很复杂,jquery 插件之间有可能存在冲突。为了尽可能避免冲突,我们可以通过 jQuery 子类来解决:
var $ = require('jquery').sub(); require('some-jquery-plugin')($);
通过 sub 方法,每个依赖 jquery 的模块,都可以得到 jQuery 的一个子类。插件往这个子类添加成员,因此各个模块之间的 jquery 是独立的了,彼此不会影响。
延续习惯
无论是共享模式还是子类模式,都不会破坏插件本身的使用方式,原来是怎么调用的,现在依旧怎么用。唯一不同的是引入方式。模块化之前,我们需要手动引入 script 标签来解决;模块化之后,我们通过 require 来管理加载和依赖。
小结
通过这种包装,我们就可以在 seajs 里使用任何 jquery 插件了,并且通过 seajs 的 node 模块,还可以让 jquery 的插件在 node 环境中运行。
一切就这么简单。看起来没什么变化,但变化就在其中!
正在为这个担心呢,插件越用越多,链接也越多,这个立马就用到新项目里,谢谢分享
bendanzz
May 18, 2011 at 22:01
妙
小豪
May 18, 2011 at 22:05
seajs应该说还刚起步,但是势头很不错,功能也做的很犀利~持续关注
小松
May 18, 2011 at 22:37
持续关注
wo_is神仙
May 19, 2011 at 10:41
不懂插件,太复杂了
诺菲尼
May 19, 2011 at 16:10
两个问题
1、require某一目录下的所有js文件(暂不考虑这些文件的依赖关系),该怎么做,require(path/*) ?
2、require某个js库,该库的粒度比较细,并且存在依赖关系,在不修改库的情况下能否保证库js文件的加载顺序?
挪墨
May 19, 2011 at 19:46
Hi, 挪墨!
第一个问题,seajs 不支持。建议可以在 path 目录下创建 index.js, 让该模块依赖本目录下的所有文件,这样 require(‘path/index’) 可以加载该目录下的所有文件。
第二个问题,seajs 也不支持。这种使用场景下,是脚本加载器的功能,推荐使用 LABjs 来实现。
lifesinger
May 19, 2011 at 21:08
不错。做到类似功能的,貌似还有do.js,module.js,require.js,using.js还有easyUi的loader.js都具体有了按需加载甚至模块管理的功能。很盼望jquery官方出一个比较实用可靠的模块管理方案。很喜欢mootools方式的。
bq69
May 21, 2011 at 17:19
不懂為什麼demo裡的dat-main=”./init” 結果去載入jquery-fancybox下的init.js 而不是載入當前目錄的init.js?
xyz
May 22, 2011 at 11:10
载的就是当前目前下的 init.js 哦
lifesinger
May 23, 2011 at 08:15
原來是相對於文檔的位置 不是相對於seajs的位置
xyz
May 23, 2011 at 08:28
用script标签只有4行代码
模块化后用了多少行代码?
xyz
May 31, 2011 at 13:49
对使用者来说,模块化后,写的代码少多了,同时默认性能高效。
lifesinger
May 31, 2011 at 14:07
使用任何一个jq的插件包括jq 应该都必须define吧,还有如果我想某些等js加载完才能使用的功能,类似thickbox的,该怎么做,一直不成功,也许我个人能力问题,请指导一下,谢谢
jie
June 15, 2011 at 18:05
你说的子类模式我在jqueryUI下用不了,其他的大部分插件都可以。
7rice
August 9, 2011 at 18:04
最后用require.async实现顺序的加载。。分享给大家试试
7rice
August 9, 2011 at 19:00
[…] jQuery 插件的模块化 « 岁月如歌. Share this:Like this:LikeBe the first to like this post. […]
jQuery 插件的模块化 « 岁月如歌 « Waht I C & What I Collect :)
August 17, 2011 at 11:15
[…] jQuery 社区中寻找各种插件来完成。大部分插件通过 jQuery 插件的模块化 […]
jQuery 模块介绍与 jQuery 插件的深度模块化 « 岁月如歌
August 19, 2011 at 22:51
[…] 2011-05-19 22:10:45| 分类: jQuery | 标签:jquery 插件 js require fancybox |字号 订阅 来源:射雕 […]
jQuery 插件的模块化
November 29, 2011 at 23:54
无法模块化 jquery.blockui 插件
ethan
March 21, 2012 at 16:20
[…] 按照 玉伯博客所写的方法 以seajs的规范把bootstrap模块化了一把,以bootstrap-tab.js为例 […]
twitter的bootstrap的模块化 « Kumalee's Blog
July 15, 2012 at 00:45
[…] 3.jQuery 插件的模块化 (可能需要翻墙) […]
转 seajs学习笔记 | ♂ヤ〇點ㄋ↙
August 6, 2012 at 21:51
你好,我最近也在学习seajs,但是js基础太差,很多地方都看不懂,能不能教我如何这个插件http://t.cn/zWnswzo,就是不知道如何去用seajs去加载传参数,希望你能指导一下,跪谢~~
xiaoxiehang37435855
August 28, 2012 at 10:57
有没有人这样做jquery插件的模块化啊, http://web322-szb.iteye.com/blog/1742930
web322
December 6, 2012 at 15:04
[…] jQuery 插件的模块化 […]
学习高富帅SEAJS,不难 « GaFish - 咳咳!!我是前端开发工程师
January 21, 2013 at 10:01
[…] 通过seajs实现前端模块化的过程中,必然需要将原有脚本改成seajs的模块。如果是一段相对独立的脚本,实现模块化的方法会比较简单,只要用define函数将原来的代码包裹起来,然后将主函数或对象用exports输出就可以了。而相比之下,将一些类库制作成模块会稍微复杂一点。比如jQuery的各种插件,实际上是依赖jQuery的,所以在模块化的时候,也必须依赖jQuery的模块。玉伯在博客里介绍了jQuery插件的模块化的方法,例如: […]
将原有的js脚本制作成seajs模块 – Dx. Yang
February 14, 2013 at 10:53