Require.js

模块化的需求

早期的js的模块化机制十分简单,在需要多文件协同的情况下,只能依赖<script>标记的加载,没有类似其它语言的import、package等管理等机制。而前端的需求越来越复杂,代码越编越多,如何更好地封装和共享代码?

  • 需要将js代码库封装起来,只暴露指定的接口,即模块化
  • 需要保证加载的js代码库之间不会产生作用域冲突
  • 模块化需要遵循统一的规范,这样该模块才能被所有的前端应用所使用
  • 需要提供便利的加载外部代码库的机制,如按名称引用和加载
  • 模块化还应提供一些额外功能,如:版本兼容检查、插件扩展机制等
  • 此外,还需要像其它语言一样,解决动态加载js文件的方法

AMD规范 与 Require.js

  • AMD: Asynchronous Module Definition 异步模块加载机制,是js中关于如何编写可共享代码库的一组规范
  • require.js 是一个基于AMD规范实现的文件和模块加载器,能够异步地加载动态的依赖

换言之,你如果希望编写可被广泛共享的代码库,且被引入时不会产生变量名冲突之类的问题,则编码时应当遵循AMD规范,然后调用者使用 require.js 来加载你的代码库,就可以避免前述的诸多问题。

  • requireJS使用document.appendChild()方法将每一个依赖加载为一个script标签。
  • requireJS等待所有的依赖加载完毕,计算出各模块定义函数的正确调用顺序,然后依次调用它们。

AMD 规范示例

// other-lib.js
define({
    $: function(s){console.log(s)}
  }
);

上述代码,定义了一个最简单的模块,该模块暴露一个名称为$的函数

结合 require.js 使用

  <script src="js/require.js"></script>
  <script> 
  require.config({
      baseUrl:'js/',  // 配置所有被引用的库默认位于 js/ 目录下
      paths:{
          'jquery':'http://cdn.com/jquery.min',
          'other':'other-lib' 
      }
  });  
  require(['jquery','other'],function($,other){
    $('#info').text('该字段不能为空!');
    other.$("this is from other-lib");  
  });  
  </script>
</body>
  • require.config定义了本地名字到文件实体的映射,即路由,如other => other-lib.js
  • 基于路由,require函数将读取第一个参数中的库名字列表,然后依次加载对应的库文件
  • 同时,基于AMD规范,将各库中define()函数所返回的对象引用作为回调函数(即require的第二个参数)的参数。上例中:$源于jquery库的$,而other-lib库虽然也定义了$,但是在主程序中,它有了命名空间other.$()。这样,就有效地避免了名称冲突。

只有一个主函数的模块

// other-lib.js
define(function () {
  return function (s){
    function(s){console.log(s)}
  };
});
//main.js
require(['jquery','other'],function($,other){
    $('#info').text('该字段不能为空!');
    other("this is from other-lib");  
  });

jquery与other这两个库虽然同时定义了一个$函数,并且作为唯一的主函数,但在main.js即调用者代码里,requirejs将其映射成为了不同的名字

其它模块化规范

参考阅读

results matching ""

    No results matching ""