JS模块化开发(requireJS)

本文详细介绍了JavaScript模块化开发的概念及其实现方式,对比了AMD和CMD两种规范,并重点讲解了RequireJS的使用方法,包括配置、加载流程、依赖管理和优化技巧。
转载至:http://blog.youkuaiyun.com/liuyan19891230/article/details/50844319

使用模块化开发的好处: 
通过 exports 暴露接口。这意味着不需要命名空间了,更不需要全局变量。这是一种彻底的命名冲突解决方案。 
通过 require 引入依赖。这可以让依赖内置,开发者只需关心当前模块的依赖,其他事情 Sea.js/ Require.js 都会自动处理好。对模块开发者来说,这是一种很好的 关注度分离,能让程序员更多地享受编码的乐趣

实现JS模块化开发,目前有两个规范,一个是AMD规范,一个是CMD规范。 
RequireJS遵循的是AMD规范。AMD推崇依赖前置。 
SeaJS遵循的CMD规范。CMD推崇依赖就近(按需加载) 
AMD:API根据使用范围有区别,但使用同一个api接口 
CMD:每个API的职责单一

AMD规范的模块风格 
1、 定义模块用module变量,它有一个方法declare 
2、 declare接受一个函数类型的参数,如称为factory 
3、 factory有三个参数分别为require、exports、module,factory使用返回值和exports导出API. factory如果是对象类型,则将该对象作为模块输出

define(function(require, exports, module) {
    var base = require('base'); 
    exports.show = function() {
    // todo with modulebase 
    } 
});
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

使用require获取依赖模块,使用exports导出API。 
除了require之外,AMD还保留了一个关键字require。require作为规范保留的全局标识符,可以实现为modile loader. 
AMD的库有RequireJS、curl、Dojo、Nodules等

requireJS和seaJS应该是各有千秋,但是因为我之前的一个项目中使用到了requireJS,所以我选择对requireJS进行深入研究。 
requireJs 
(1)实现js文件的异步加载,避免网页失去响应; 
(2)管理模块之间的依赖性,便于代码的编写和维护。

RequireJS用法介绍。 
requirejs官网是: http://requirejs.org/ 
官方下载地址:http://requirejs.org/docs/release/2.1.20/minified/require.js 
先下载require.js.

require.config是用来定义别名的,在paths属性下配置别名。然后通过requirejs(参数一,参数二);参数一是数组,传入我们需要引用的模块名,第二个参数是个回调函数,回调函数传入一个变量,代替刚才所引入的模块。 
require.js的加载 
1、在页面底部加载。 
2、<script src="js/require.js" defer async="true" ></script> 
async属性表面这个文件需要异步加载,避免网页失去响应,IE不支持async,需要使用defer属性。 
加载require.js以后,下一步就要加载我们自己的代码了。

<script src="js/require.js" data-main="js/main"></script>
 
  • 1
  • 1

data-main属性的作用是,指定网页程序的主模块。 
main.js文件 
这里写图片描述 
引入模块也可以只写require()。requirejs通过define()定义模块,定义的参数上同。在此模块内的方法和变量外部是无法访问的,只有通过return返回才行. 
require的项目中,所有需要引入的文件都不要写.js的后缀名,因为requirejs会自动添加.js的后缀名。 
define 模块 
这里写图片描述 
将该模块命名为math.js保存。 
define 定义模块方法只能用在独立的js文件中,不能在页面中直接使用。 
否则会报 Mismatched anonymous define() module 错误。 
没有依赖 
如果定义的模块不依赖其他模块,则可以: 
这里写图片描述 
AMD推荐的风格通过返回一个对象做为模块对象,CommonJS的风格通过对module.exports或exports的属性赋值来达到暴露模块对象的目的。 
当写一个没有任何依赖的模块,并且只是返回一个对象包含一些功能函数 
这里写图片描述 
循环依赖 
在一些情况中,我们可能需要模块moduleA和moduleA中的函数需要依赖一些应用。这就是循环依赖。 
这里写图片描述 
math.js引入模块方法 
这里写图片描述

AMD规范定义的require()函数:

require(['moduleA', 'moduleB', 'moduleC'], 
    function (moduleA, moduleB, moduleC){
    // some code here
  });
 
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

require()函数接受两个参数。第一个参数是一个数组,表示所依赖的模块,上例就是[‘moduleA’, ‘moduleB’, ‘moduleC’],即主模块依赖这三个模块;第二个参数是一个回调函数,当前面指定的模块都加载成功后,它将被调用。加载的模块会以参数形式传入该函数,从而在回调函数内部就可以使用这些模块。 
require()异步加载moduleA,moduleB和moduleC,浏览器不会失去响应;它指定的回调函数,只有前面的模块都加载成功后,才会运行,解决了依赖性的问题。 
假定主模块依赖jQuery、underscore和backbone这三个模块,main.js就可以这样写:

require(['jquery', 'underscore', 'backbone'], function ($, _, Backbone){
    // some code here
  });
 
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

require.js会先加载jQuery、underscore和backbone,然后再运行回调函数。主模块的代码就写在回调函数中。

模块的加载

主模块的依赖模块是[‘jquery’, ‘underscore’, ‘backbone’]。默认情况下,require.js假定这三个模块与main.js在同一个目录,文件名分别为 jquery.js,underscore.js和backbone.js,然后自动加载。 
使用require.config()方法,我们可以对模块的加载行为进行自定义。require.config()就写在主模块(main.js)的头部。参数就是一个对象,这个对象的paths属性指定各个模块的加载路径。 
这里写图片描述 
上面的代码给出了三个模块的文件名,路径默认与main.js在同一个目录(js子目录)。如果这些模块在其他目录,比如js/lib目录,则有两种写法。一种是逐一指定路径。 
这里写图片描述 
另一种则是直接改变基目录(baseUrl)。 
这里写图片描述 
如果某个模块在另一台主机上,也可以直接指定它的网址,比如: 
这里写图片描述 
require.js要求,每个模块是一个单独的js文件。这样的话,如果加载多个模块,就会发出多次HTTP请求,会影响网页的加载速度。因此,require.js提供了一个优化工具,当模块部署完毕以后,可以用这个工具将多个模块合并在一个文件中,减少HTTP请求数。 
在代码中require一个文件多次,不会导致浏览器反复加载,即使反复require它,它也只加载一次。 
CDN回退,当CDN加载不正确时,回退到本地相应的库2,通过require.config实现。 
这里写图片描述

AMD模块的写法

require.js加载的模块,采用AMD规范。也就是说,模块必须按照AMD的规定来写。 
具体来说,就是模块必须采用特定的define()函数来定义。如果一个模块不依赖其他模块,那么可以直接定义在define()函数之中。 
//math.js 
这里写图片描述 
加载方法如下: 
这里写图片描述 
如果这个模块还依赖其他模块,那么define()函数的第一个参数,必须是一个数组,指明该模块的依赖性。 
这里写图片描述 
当require()函数加载上面这个模块的时候,就会先加载myLib.js文件。

加载非规范的模块

理论上,require.js加载的模块,必须是按照AMD规范、用define()函数定义的模块。但是实际上,虽然已经有一部分流行的函数库(比如jQuery)符合AMD规范,更多的库并不符合.require.js能够加载非规范的模块,方法是,在用require()加载之前,要先用require.config()方法定义它们的一些特征。 
举例来说,underscore和backbone这两个库,都没有采用AMD规范编写。如果要加载它们的话,必须先定义它们的特征。 
这里写图片描述 
require.config()接受一个配置对象,这个对象除了有前面说过的paths属性之外,还有一个shim属性,专门用来配置不兼容的模块。具体来说,每个模块要定义(1)exports值(输出的变量名),表明这个模块外部调用时的名称;(2)deps数组,表明该模块的依赖性。 
这里写图片描述

得到模块的地址

var path = require.toUrl("./style.css");
 
  • 1
  • 1

JSONP

这里写图片描述

require.js插件

require.js还提供一系列插件,实现一些特定的功能。 
domready插件,可以让回调函数在页面DOM结构加载完成后再运行。 
这里写图片描述 
text和image插件,则是允许require.js加载文本和图片文件 
这里写图片描述 
类似的插件还有json和mdown,用于加载json文件和markdown文件。

r.js压缩

Require.js 提供一个脚本 r.js ,可以将所有使用到的模块压缩成一个脚本文件,r.js 可以使用Node.js 来执行。 
在压缩模块前,需要写一个配置文件,说明主模块名,压缩后的文件名,哪些模块不要压缩 
没有使用 define 定义的模块都不要压缩,包括 jquery,backbone 等库及其插件

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值