AMD 异步模块加载

1.CommonJS

node.js 即采用的commonJS的规范。
在node.js中,除了函数作用域外还有一个模块作用域,模块设计模式也因此体现,node就是基于模块编程,各个模块互不影响,耦合性很低,因此我们通常用一个模块封装一个功能。
在node 中,模块又分为两类,核心模块和文件模块。用户自定义模块的就是文件模块,下面我们来看看node里模块的定义与导入

1.1CommonJS里模块的定义

在文件模块中,一个文件就是一个模块,因此我们只需定义暴露给外部的接口就行。
比如下面我们声明一个sum函数,来计算两个数的和,将它暴露给外部调用,下面是实现代码:

let sum = (x,y) => {
    return x + y;
};
module.exports = sum;

以上的代码都在一个模块的作用域里,module 是这个模块的顶层作用域,exports 初始化指向一个空对象,module.exports 是实际导出的接口,实际上exports指向module.exports的引用,如果exports发生改变,实际导出的还是module.exports。

这里我把sum函数当作外部接口暴露给外部调用。这里一个简单的模块就定义完成了,接下来我在另一个模块里去调用它。

1.2CommonJS里模块的导入

调用代码如下

console.log(require("test46.js")(1,2));

打印出来的结果 : 3

这里我们直接把它打印出来。以上代码等价于

let sum = require("test46.js");
console.log(sum(1,2));

我们直接调用了之前定义的模块,因此可以直接调用它暴露给我们的函数。

2.AMD异步模块加载

node作为一个服务端语言,在加载模块时,模块都是在本地磁盘,因此可以以可观的速度加载进来,因此,在node里的模块加载都是同步的,阻塞时间都不会太长。

但是如果我们要在浏览器端的js来实现模块设计模式呢,这就意味着我们需要远程从服务器加载所以定义的模块,浏览器js引擎的阻塞时间可想而知。
如果不使用模块设计模式的话,那各个js文件互相依赖,而且共享一个顶层作用域window,很容易出现变量重定义的错误。比如下面这种形式

<script src="js/test1.js" type="text/javascript" charset="utf-8"></script>
        <script src="js/test2.js" type="text/javascript" charset="utf-8"></script>
        <script src="js/test3.js" type="text/javascript" charset="utf-8"></script>
        <script src="js/test4.js" type="text/javascript" charset="utf-8"></script>
        <script src="js/test5.js" type="text/javascript" charset="utf-8"></script>
        <script src="js/test6.js" type="text/javascript" charset="utf-8"></script>

各个文件互相依赖,耦合性很高。

但是如果我们要用模块设计模式的话,那么各个模块必须用异步加载,如果不用异步加载,浏览器很可能处于很长时间的阻塞状态,造成很糟糕的用户体验。因此AMD孕育而生。

下面我们看看AMD的模块定义。

2.1.1 AMD 没有依赖于其他模块的模块定义

我们的模块可以用define来定义。

define(arr[],function(){});

define 接受两个参数,第一个参数可以省略,在没有依赖于其他模块的情况下,可以将第一个参数省略,因此,我们可以这样定义。

define(() => {
    let sum = (x,y) => {
        return x + y;
    };
    return {sum:sum}
});

与commonJS 也有一些相似之处,commonJS 暴露给外部的接口为module.exports 所指向的对象,而AMD 暴露给外部的接口为return 的对象,这里我暴露了一个json对象,key 为外部调用的名称,value 为名称指向的对象。

2.1.2 AMD 依赖于其他模块的模块定义

如果我们定义的模块依赖于其他的模块,比如我们依赖于一个hello的模块。
这时,我们的模块需要这样定义

define(['hello'],() => {
    let sum = (x,y) => {
        return x + y;
    };
    return {sum:sum}
});

我们假定hello 模块和当前定义的模块在同一个目录下,因此我们直接写上模块名就行,如果没有在同一目录下需要加上路径。另外还可以通过require.config()方法来配置。

require.config(
    path:{
        "hello":"js/hello.js"
    }
);

2.2.1 AMD 加载模块

同commonJS加载模块很相似的是,也是通过require方法来加载模块。

require(arr[],callback);

require方法接受两个参数,第一个参数为一个数组,代表需要加载的模块,第二个参数为一个回调函数。

假定我们要加载一个jquery 库,我们可以这样做:

require("jquery",$ => {
    //some code here
});

说了这么多,我们要怎么来使用AMD 异步模块加载呢,我们需要先去require.js 官网下载,然后将它用script标签引入即可
http://requirejs.org/docs/download.html (download)

<script src="js/require.js" type="text/javascript" defer="defer" async="true" charset="utf-8"></script>

defer 属性规定当页面已完成加载后,才会执行脚本,async 属性则是规定该标签会异步加载。

这时我们已经异步把require.js 加载进来了,之后,我们需要规定一个主模块。程序将从这里开始执行。
这时我们只要指定一个 data-main属性即可,假定我们已经有main.js这个文件

<script src="js/require.js" type="text/javascript" data-main="js/main" charset="utf-8"></script>

直到这里,我们已经知道了如何去在前端实现模块设计模式的使用方法

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值