require.js实现js模块化编程(一)

1、认识require.js: 官方文档:http://requirejs.org/ RequireJS是一个非常小巧的JavaScript模块载入框架,是AMD规范最好的实现者之一。最新版本的RequireJS压缩后只有14K,堪称非常轻量。它还同时可以和其他的框架协同工作,使用RequireJS必将使您的前端代码质量得以提升。 RequireJS 是一个JavaScript模块加载器。它非常适合在浏览器中使用, 但它也可以用在其他脚本环境, 就像 Rhino and Node. 使用RequireJS加载模块化脚本将提高代码的加载速度和质量。 2、require.js的优点: 2.1、异步加载,防止js阻塞页面渲染; 2.2、按需加载,避免在初始化网页的时候,产生大量的请求和数据传输;防止出现如下丑陋的场景: 2.3、更加方便的模块依赖管理。相信你曾经一定遇到过因为script标签顺序问题而导致依赖关系发生错误,这个函数未定义,那个变量undefine之类的。通过RequireJS的机制,你能确保在所有的依赖模块都加载以后再执行相关的文件,所以可以起到依赖管理的作用。 2.4、更加高效的版本管理。想一想,如果你还是用的script脚本引入的方式来引入一个jQuery2.x的文件,然后你有100个页面都是这么引用的,那当你想换成jQuery3.x,那你就不得不去改这100个页面。但是如果你的requireJS有在config中做jQuery的path映射,那你只需要改一处地方即可。 3、在网页中未使用require.js和使用require.js比较 网页中未使用require.js编写方式: index.html: 1 2 3 4 5 6 7 8 9 body a.js: 1 2 3 4 function fun1(){ alert("it works"); } fun1(); 可能你更喜欢这样写: a.js: 1 2 3 4 5 6 (function(){ function fun1(){ alert("it works"); } fun1(); })() 第二种方法使用了块作用域来申明function防止污染全局变量,本质还是一样的,当运行上面两种例子时不知道你是否注意到,alert执行的时候,html内容是一片空白的,即body并未被显示,当点击确定后,才出现,这就是JS阻塞浏览器渲染导致的结果。 使用require.js写法: index.html 1 2 3 4 5 6 7 8 9 10 11 12 body a.js 1 2 3 4 5 6 define(function(){ function fun1(){ alert("it works"); } fun1(); }) 浏览器提示了"it works",说明运行正确,但是有一点不一样,这次浏览器并不是一片空白,body已经出现在页面中。 4、熟悉requirejs基本API require会定义三个变量:define,require,requirejs,其中require === requirejs,一般使用require更简短; 一个回调函数:callback ● define 从名字就可以看出这个api是用来定义一个模块 ● require 加载依赖模块,并执行加载完后的回调函数 ● callback,一个function,是用来处理加载完毕后的逻辑 用define定义模块的方法如下:【function定义法】 如果index.html,main.js,js文件夹为平级目录,a.js和jquery.js位于js文件夹下, a.js【AMD规范的写法】 1 2 3 4 5 6 7 8 9 10 11 12 13 14 define(function() { var target = null; function countTool() { target = this; target.value = 0; }; countTool.prototype.add = function(a, b) { return a + b; }; countTool.prototype.minus = function(a, b) { return a - b; }; return countTool; }); 用require 加载依赖模块,没有用到callback回调函数,方法如下: main.js 1 require(["js/a"]); 来加载该模块(注意require中的依赖是一个数组,即使只有一个依赖,你也必须使用数组来定义). require API的第二个参数是callback,一个function,是用来处理加载完毕后的逻辑,如: main.js 1 2 3 require(["js/a"],function(countTool){ countTool.add(2,3); }) 会得到结果为:5 如上的写法,我们发现require()第一个数组的参数中,添加的a.js的写法["js/a"]较繁琐。但可以使用require.config()来进行优化。 5、用require.config()来加载文件 之前的例子中加载模块都是本地js,但是大部分情况下网页需要加载的JS可能来自本地服务器、其他网站或CDN,这样就不能通过这种方式来加载了,我们以加载一个jquery库为例: main.js 1 2 3 4 5 6 7 8 9 10 11 12 13 require.config({ paths : { "jquery" : ["http://libs.baidu.com/jquery/2.0.3/jquery"], // paths还可以配置多个路径,如果远程cdn库没有加载成功,可以加载本地的库,如下: // "jquery" : ["http://libs.baidu.com/jquery/2.0.3/jquery", "js/jquery"], "a" : "js/a" } }) require(["jquery","a"],function($,a){ $(function(){ a.add(2,3); // 5 }) }) 在使用requirejs时,加载模块时不用写.js后缀的,当然也是不能写后缀 6、requirejs的使用方法 6.1、首先要到requirejs的网站去下载js -> requirejs.org或者到我的网盘下载; 6.2、然后在index.html页面中使用下面的方式来使用requirejs 1   相关参数解析如下: (1)、加载requirejs脚本的script标签加入了data-main属性,是指当reuqire.js加载完成之后,就可以使用这个配置文件(main.js)来直接使用require来加载所有的短模块名。 (2)、当script标签指定data-main属性时,require会默认的将data-main指定的js为根路径,是什么意思呢?如上面的data-main="js/main"设定后,我们在使用require(['jquery'])后(不配置jquery的paths),require会自动加载js/jquery.js这个文件,而不是jquery.js,相当于默认配置了: 1 2 3 require.config({ baseUrl : "js" }) (3)、async属性表明这个文件需要异步加载,避免网页失去响应。 (4)、IE的异步加载,只支持defer,所以把defer也写上。 6.3、添加全局配置文件main.js 注意:前提是需要在js/libs文件夹下放入jquery.js和a.js,并且a.js要实现AMD规范的写法,参照上面的a.js. main.js 1 2 3 4 5 6 7 8 9 10 require.config({ paths : { "jquery" : "./libs/js/jquery", "a" : ".libs/js/a" } }) require(["jquery","a"],function($,a){ console.log($); a.add(2,3); // 5 }) 另外一种优化paths的方法为:使用参数baseUrl,前提是js/jquery.js,js/a.js如下:另外一种优化paths的方法为:使用参数baseUrl,前提是js/jquery.js,js/a.js如下: main.js 1 2 3 4 5 6 7 8 9 10 11 require.config({   baseUrl: "js/lib",   paths: {     "jquery": "jquery",     "a": "a"   } }); require(["jquery","a"],function($,a){ console.log($); a.add(2,3); // 5 }) 6.4、a.js实现AMD规范的写法 require.js加载的模块,采用AMD规范。也就是说,模块必须按照AMD的规定来写。 具体来说,就是模块必须采用特定的define()函数来定义。如果一个模块不依赖其他模块,那么可以直接定义在define()函数之中。 require定义一个模块是通过 define = function (name, deps, callback)完成的,第一个参数是定义模块名,第二个参数是传入定义模块所需要的依赖,第三个函数则是定义模块的主函数,主函数和require的回调函数一样,同样是在依赖加载完以后再调用执行。 如下,没有依赖模块的写法。假定现在有一个a.js文件,它定义了一个a模块。那么,a.js就要这样写: a.js 写法一: 直接定义方法 View Code a.js 写法二: 方法衍生法 View Code a.js 写法三: 对象定义法 View Code 加载方法如下: main.js 1 2 3 require(['a'], function (a){   alert(a.add(1,1)); // 2 }); 如果这个模块还依赖其他模块,那么define()函数的第一个参数,必须是一个数组,指明该模块的依赖性。 依赖对象定义,如: b.js,假设b.js中定义乘法和除法方法。 View Code 当require()函数加载上面这个模块的时候,就会先加载a.js文件。 为什么我始终都没有使用name来定义自己的模块名: 如果你细心,你可能会发现,刚刚define函数,有一个参数name是用来定义模块名的(也就是第一个传参),为什么上面两个例子都没有用到。其实我确实可以添加模块名,如下: 1 2 3 define('b',['./b'],function(b){ ..... }) 但是,这样做感觉不很有必要,因为如果哪一天我将这个文件转移到其他目录下,那我就得在这这里再修改一次模块名。官方其实也不推荐,用官方的说法是:让优化工具去自动生成这些模块名吧! 6.5、加载非规范化模块 理论上,require.js加载的模块,必须是按照AMD规范、用define()函数定义的模块。但是实际上,虽然已经有一部分流行的函数库(比如jQuery)符合AMD规范,更多的库并不符合。那么,require.js是否能够加载非规范的模块呢? 回答是可以的。 那么如何判断一个js库,有没有采用AMD规范?只需看其js库中,有没有实现define.amd相关的判断代码即可; 如jQuery中实现AMD的代码如下: 1 2 3 4 5 if ( typeof define === "function" && define.amd ) { define( "jquery", [], function() { return jQuery; } ); } underscore.js v1.6中AMD的代码如下: 1 2 3 4 5 if (typeof define === 'function' && define.amd) { define('underscore', [], function() { return _; }); } jQuery 从 1.7 版本开始支持了 AMD 对其类库的加载,所以开发者可以通过 require 方法来异步加载 jQuery 的源代码。 underscore.js从1.6,backbone.js从1.1.1版本之后开始支持了 AMD 对其类库的加载; 例如,如果用到underscore.js v1.6或者backbone.js v1.1.1之前的版本,这样的模块在用require()加载之前,要先用require.config()方法,定义它们的一些特征。这里需要用到shim{},专门用来配置不兼容的模块,如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 require.config({   shim: {       'underscore':{         exports: '_'       },       'backbone': {         deps: ['underscore', 'jquery'],         exports: 'Backbone'       }, 'jquery.scroll': {        deps: ['jquery'],        exports: 'jQuery.fn.scroll'      }   } }); 如:dateUtil.js,没有用define()来定义。 1 2 3 4 5 6 7 8 (function(window) { var DateUtils = {}; DateUtils.toString = function() { alert("toString"); }; // 全局变量 window.DateUtils = DateUtils; })(window); 加载该模块的方法如下: 1 2 3 4 5 6 7 8 require.config({ shim:{ dateUtil:{ deps:[], exports:'dateUtil' } } }); 具体来说,每个模块要定义 (1)deps数组,表明该模块的依赖性。 (2)exports值(输出的变量名),表明这个模块外部调用时的名称; 7、require.js提供了一个优化工具r.js require.js提供了一个优化工具r.js或者到网盘下载,当模块部署完毕以后,可以用这个工具将多个模块合并在一个文件中,减少HTTP请求数。 具体使用方法,请参考下节:require.js实现js模块化编程(二):RequireJS Optimizer 8、相关文档: ● JavaScript模块化编程 - CommonJS, AMD 和 RequireJS之间的关系 ● RequireJS英文官方文档 require.js,实现具体的项目构建,请自行下载,谢谢关注。 你的关注和支持是对我最大的动力~ 书山有路群[一个非常活跃的读书分享群,每周都有新书分享]:452450927 微博:http://weibo.com/u/2241641312 出处:http://www.cnblogs.com/wdlhao/ github:https://github.com/wdlhao 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面 好文要顶 关注我 收藏该文 http://www.cnblogs.com/wdlhao/p/7749756.html
50000+
5万行代码练就真实本领
17年
创办于2008年老牌培训机构
1000+
合作企业
98%
就业率

联系我们

电话咨询

0532-85025005

扫码添加微信