fangchaolong
文章57
标签24
分类10
javascript模块化-AMD

javascript模块化-AMD

AMD Async Module Definition代表的意思为异步模块定义,是Javascript模块化的浏览器解决方案,它采用异步的方式加载模块,模块的加载不影响它后面语句的运行。所有依赖这个模块的语句,都定义在回调函数中,等到加载完成之后,这个回调函数才会运行。

active

AMD规范定义了一个函数define,通过define方法定义模块:

 define(id?, dependencies?, factory);

并且采用require()语句加载模块:

require([module], callback);

引入的模块和回调函数不是同步的,所以浏览器不会因为引入的模块加载不成功而假死。

RequireJS

RequireJS是一个基于AMD规范实现的JavaScript文件和模块加载器。它针对浏览器内使用进行了优化,并且对其他JS环境(Rhino和Node)做了兼容。使用RequireJS这样的模块化脚本加载器可以提高代码的速度和质量。

  1. 异步加载:使用 RequireJS,会在相关的 js 加载后执行回调函数,这个过程是异步的,所以它不会阻塞页面。

  2. 按需加载:通过 RequireJS,你可以在需要加载 js 逻辑的时候再加载对应的 js 模块,不需要的模块就不加载,这样避免了在初始化网页的时候发生大量的请求和数据传输。

基本使用

根据官方文档和项目实例,接下来说一下ReuqireJS的基本使用:

Reuqire Download

下载最新版的RequireJS

Project Structure

下面是官方示例的RequireJS项目结构,对内容做了小小的改动,www作为项目的根目录,lib中存放项目依赖即需要的一些JS库,app.js为主入口文件,app中存放自己写的模块文件。

active

Project Code

1. index.html

index.html中定义了一个script标签来引入require.js,其中data-main属性是一个自定义属性,这个属性指定在加载完 reuqire.js 后,就将属性指定路径下的JS文件并运行,这个文件即入口文件,这里的app.jsjs后缀被省略掉了。

<!DOCTYPE html>
<html>
    <head>
        <script data-main="app" src="lib/require.js"></script>
    </head>
    <body>
        <h1>Hello World</h1>
    </body>
</html>

如果 <script/> 标签引入 require.js 时没有指定 data-main 属性,则以引入该 jshtml 文件所在的路径为根路径,如果有指定 data-main 属性,也就是有指定入口文件,则以入口文件所在的路径为根路径。

2. app.js

Main.js加载主模块并且配置项目依赖,要改变 RequireJS的默认配置,可以使用require.config函数传入一个可选参数对象。下面是一些可以使用的配置:

// For any third party dependencies, like jQuery, place them in the lib folder.

// Configure loading modules from the lib directory,
// except for 'app' ones, which are in a sibling
// directory.
requirejs.config({
  // 模块加载的根路径。
  baseUrl: ".",
     // 用于一些常用库文件或者文件夹路径映射,js后缀可以省略
  paths: {
    app: "app/",
    fmt: "lib/fmt",
  },
});

// Start loading the main app file. Put all of
// your application logic in there.
requirejs(["app/main"]);

如果在 require.config() 中有配置 baseUrl,则以 baseUrl 的路径为根路径,这条规则会覆盖上面data-main的效果。

3. app/

Main.js中我们通过require函数加载了一个message模块,该模块用于打印一些定义好的字符串。

define(function (require) {
  var msg = require("./message");
  msg.helloWorld();
});

Main.js中使用的模块定义在message.js中,他引入了一个输出依赖fmt

define(["fmt"], function (fmt) {
  return {
    helloWorld: function () {
      fmt.println("hello word");
    },
  };
});

这两种依赖的加载方式又和不同稍后介绍。

4. lib/

Lib/fmt.js中我定义一个 js 模块模拟gofmt包,通过return对外暴露出接口。注意,暴露的对象就是引入的对象。

define(function () {
  var print = function (msg) {
    console.log(msg);
  };
  var println = function (msg) {
    console.log(msg + "\n");
  };

  return {
    moduleName: "fmt",
    print: print,
    println: println,
  };
});

无以生计,卖文苟延

微信
支付宝