模块化编写JavaScript,在web前端程序不断扩大的时候,是一个很好的重构技术。
下面的例子有两个模块,
artDialog模块依赖jquery和jquery.artDialog库,提供了弹出错误对话框的功能。
require.config({ paths: { "jquery": "../thirdParty/jquery-1.8.0.min", "jquery.artDialog": "../../plugin/artDialog4.1.6/jquery.artDialog" } }); define("artDialog", ["jquery", "jquery.artDialog"], function ($, artDialog) { return { cancelText: "", language: "", // language should be either 'cn' or 'en' init: function (language) { this.language = language; if (language === "cn") { this.cancelText = "取消"; } else { this.cancelText = "Cancel"; } }, error: function (message) { $.dialog({ icon: "error", content: message, cancelVal: this.cancelText, ok: function () { this.close(); } }); } }; } );
1.require.config里面的paths 用了key: value形式,key是名称简写,path是从当前位置找到依赖文件的路径
2.define是定义模块的意思,第一个参数"artDialog"是指这个模块的名称,数组里面是本模块依赖的其他js模块,
3.RequireJS看到2定义的依赖模块后,会去加载这些js文件,加载完成后,会调用函数function($, artDialog)
4.回调函数反回一个json对象,里面有成员变量和函数。
ajaxUtility模块内部使用了artDialog模块,看看代码:
require.config({ paths: { "jquery": "../thirdParty/jquery-1.8.0.min", "artDialog": "./dialog" } }); define("ajaxUtility", ["jquery","artDialog"], function ($, artDialog) { return { cancelText: "", language: "", // language should be either 'cn' or 'en' init: function (language) { this.language = language; artDialog.init(language); if (this.language === "cn") { this.cancelText = "取消"; } else { this.cancelText = "Cancel"; } }, // popup an error dialog defualtErrorHandler: function (jqXHR, textStatus) { artDialog.error("Ajax request got an error:" + textStatus); }, // execute .ajax function and except the returned data type is json // handler(msg) will be callback when .ajax succeeded // errorHandler(jqXHR, textStatus) willl be callback if .ajax failed exe: function (urlPath, asyncWay, method, dataValue, handler, errorHandler, context) { var error, request; if (errorHandler) { error = errorHandler; } else { error = this.defaultErrorHandler; } request = $.ajax({ url: urlPath, async: asyncWay, type: method, dataType: 'json', data: dataValue }); // request.done(handler); request.done( (function (ob, hdl) { return function(msg) { hdl(ob, msg); } })(context, handler) ); request.fail(error); }, // post data to server using .ajax // handler(msg) will be callback when .ajax succeeded // errorHandler(jqXHR, textStatus) willl be callback if .ajax failed post: function (urlPath, asyncWay, dataValue, handler, errorHandler, context) { this.exe(urlPath, asyncWay, 'POST', dataValue, handler, errorHandler, context); }, // call web method with GET to server using .ajax // handler(msg) will be callback when .ajax succeeded // errorHandler(jqXHR, textStatus) willl be callback if .ajax failed get: function (urlPath, asyncWay, dataValue, handler, errorHandler, context) { this.exe(urlPath, asyncWay, 'GET', dataValue, handler, errorHandler, context); } }; } );
2.define语句定义了ajaxUtility模块,并且在加载dialog.js文件和jquery完成后,调用函数function($, artDialog) ,注意,此时参数artDialog就是前面一个模块返回出来的对象。
依赖加载的说明,chrome调试发现,不用担心共同依赖的jquery会被加载两次,RequireJS很智能。也不用担心依赖顺序,只要每个模块都正确定义了自己的依赖模块,顺序就会有保障。
最后给一个第三个模块演示如何依赖这两个模块,以及其他模块:
require.config({ paths: { "ajaxUtility": "./ajax_utility", "jquery.validate": "../../plugin/jquery-validation-1.9.0/jquery.validate.min", "flexigrid": "../../plugin/flexigrid-1.1/js/flexigrid", "flexigrid.pack": "../../plugin/flexigrid-1.1/js/flexigrid.pack", "jquery.ui": "../../plugin/jquery-ui-1.8.23.custom/js/jquery-ui-1.8.23.custom.min" } }); require(["ajaxUtility"], function(ajaxUtility) { ajaxUtility.init("cn"); require(["jquery.validate", "flexigrid", "flexigrid.pack", "language", "jquery.ui"], function(util) { require(["log"], function(util) { $(document).ready(function() { log.init(); }) }); }); });最外层的require加载的是ajaxUtility,因此它最先被加载,juery, jquery.artDialog和dialog.js都会被加载,然后其他依赖比如jquery.ui就无须担心jquery是否加载。