【js-10】如何使用requirejs?

小课堂【武汉第237期】

分享人:肖浩宇

目录

1.背景介绍

2.知识剖析

3.常见问题

4.解决方案

5.编码实战

6.扩展思考

7.参考文献

8.更多讨论

1.背景介绍

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

            

   
  
  
  
  
  
            
        

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


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

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

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的用法

参考二:RequireJS和AMD规范

8.更多讨论

感谢观看

BY : 肖浩宇