如何使用requirejs?

1.背景介绍

最早的时候,所有Javascript代码都写在一个文件里面,只要加载这一个文件就够了。后来,代码越来越多,一个文件不够了,必须分成多个文件,依次加载。下面的网页代码,相信很多人都见过。


  

  

  

  

  

这样的写法有很大的缺点。首先,加载的时候,浏览器会停止网页渲染,加载文件越多,网页失去响应的时间就会越长;其次,由于js文件之间存在依赖关系,因此必须严格保证加载顺序(比如上例的1.js要在2.js的前面),依赖性最大的模块一定要放到最后加载,当依赖关系很复杂的时候,代码的编写和维护都会变得困难。

require.js的诞生,就是为了解决这两个问题:

1.实现js文件的异步加载,避免网页失去响应;
2.管理模块之间的依赖性,便于代码的编写和维护。

2.知识剖析

1、require.js的加载


其中,data-main属性的作用是,指定网页程序的主模块。在上例中,就是js目录下面的main.js,这个文件会第一个被require.js加载。由于require.js默认的文件后缀名是js,所以可以把main.js简写成main。

2、主模块的写法

main.js,我把它称为"主模块",意思是整个网页的入口代码。主模块依赖于其他模块,这时就要使用AMD规范定义的的require()函数:

// main.js
  require(['moduleA', 'moduleB', 'moduleC'], function (moduleA, moduleB, moduleC){
    // some code here
  });

require()函数接受两个参数。第一个参数是一个数组,表示所依赖的模块,第二个参数是一个回调函数,当前面指定的模块都加载成功后,它将被调用。

3、模块的加载

如刚才的例子,默认情况下,require.js假定这三个模块与main.js在同一个目录,文件名分别为moduleA.js,moduleB.js和moduleB.js,然后自动加载。

4、AMD模块的写法

require.js加载的模块,采用AMD规范。也就是说,模块必须按照AMD的规定来写。具体来说,就是模块必须采用特定的define()函数来定义。如果一个模块不依赖其他模块,那么可以直接定义在define()函数之中。,如main.js:

// math.js
define(function (){
return {
add: add = function (x,y){
return x+y;
}
}
});


main.js的加载方法如下:


  // main.js
  require(['math'], function (math){
    alert(math.add(1,1));
  });

3.常见问题

不符合AMD规范的模块怎么加载?

4.解决方案

理论上,require.js加载的模块,必须是按照AMD规范、用define()函数定义的模块。但是实际上,虽然已经有一部分流行的函数库(比如jQuery)符合AMD规范,更多的库并不符合。

这样的模块在用require()加载之前,要先用require.config()方法,定义它们的一些特征。 举例来说,underscore和backbone这两个库,都没有采用AMD规范编写。如果要加载它们的话,必须先定义它们的特征。

require.config({
    shim: {
      'underscore':{
        exports: '_'
      },
      'backbone': {
        deps: ['underscore', 'jquery'],
        exports: 'Backbone'
      }
    }
  });

require.config()接受一个配置对象,这个对象除了有前面说过的paths属性之外,还有一个shim属性,专门用来配置不兼容的模块。具体来说,每个模块要定义:
1.exports值(输出的变量名),表明这个模块外部调用时的名称;
2.deps数组,表明该模块的依赖性。

5.编码实战

DEMO

6.扩展思考

js的模块写法有哪些规范?

目前,通行的Javascript模块规范共有两种:CommonJS和AMD。
CommonJS主要用于服务器端,写法为:

     var math = require('math');
      math.add(2,3); // 5

第二行math.add(2, 3),在第一行require('math')之后运行,因此必须等math.js加载完成。也就是说,如果加载时间很长,整个应用就会停在那里等。这是一种同步加载,在加载模块时会使浏览器处于"假死"状态。

AMD为异步加载方案,写法为:

    require(['math'], function (math) {
        math.add(2, 3);
      });

math.add()与math模块加载不是同步的,浏览器不会发生假死。所以很显然,AMD比较适合浏览器环境。

7.参考文献

参考一:Javascript模块化编程(三):require.js的用法
参考二:nRequireJS和AMD规范

8.更多讨论

1.在两个js文件的define中定义相同的对象属性会如何?

不会有冲突,在main中使用require加载时,在回调函数中将各个依赖模块都定义了输出的变量名,两个属性名虽然相同,但是属性的对象名是不一样的。

2.require()中依赖的模块全部加载完成后,回调函数才会执行吗?

不是,在摸一个模块加载完成后,依赖这个模块的代码就会执行。

你可能感兴趣的:(如何使用requirejs?)