回头再看JS模块化编程之AMD

回头再看JS模块化编程之AMD

由于CommonJS采用适合服务器端的同步加载方式,这种方式不适合天生异步的浏览器端。在这种形势下,AMDAsynchronous Module Definition,异步模块定义)应运而生。require.js正是AMD规范下的产物,因此,我们可以直观地从require.js入手分析AMD

require.js

这是RequireJS官方下载链接,我本次测试使用的是2.3.5版本。

加载require.js

使用RequireJS后,我们不用在html中手动添加蛮蛮多的script标签了,通过模块依赖的方式,RequireJS会自动创建script标签,也使得模块间依赖关系的管理变得更加方便。首先,需要在html中引入require.js,并通过data-main属性指定入口js文件

1
<script src="./js/amd/require-2.3.5.js" data-main="./js/amd/main" defer async></script>

定义模块

我们先不关注main.js的实现,先来看看在RequireJS中怎么定义模块。

1
2
// name和deps都是非必选的参数,而callback可以是一个对象,或者是具有返回值的函数
define([name], [deps], callback)

简单模块

如果一个模块只包含一些键值对,没有任何依赖,则在define()中定义这些键值对就好了

1
2
3
4
5
6
7
8
// 定义模块时,推荐不显示传入name参数,这样方便优化工具去生成。
define({
name: 'simpleModule',
version: '1.0.0',
add: function(a, b) {
return a + b;
}
})

函数式模块

跟上篇文章说到的IIFE是一样的道理,加入我们需要对模块做一些初始化的工作,那么就不能使用简单模块的定义方式了。函数式模块的定义方式如下:

1
2
3
4
5
6
7
8
9
10
11
define(function() {
// ...
// 这之前可以做一些初始化的变量赋值等等...
function add(a, b) {
return a + b
}
// 最终return一个对象,暴露给调用者使用
return {
add: add
}
})

存在依赖的模块

假设你要写一个依赖jquery的模块,那么你需要在define方法中声明依赖。

1
2
3
4
5
6
7
8
define(['jquery'], function($) {
function setColor(select, color) {
$(select).css('color', color)
}
return {
setColor: setColor
}
})

在官网上还发现一种类似sea.js的依赖写法。

1
2
3
4
5
6
7
8
9
define(function(require, exports, module) {
var $ = require('jquery')
function setColor(select, color) {
$(select).css('color', color)
}
return {
setColor: setColor
}
})

我的猜想:这种写法的代码在运行时,当前模块不知道所依赖的外部模块有哪些,需要遍历所有的require关键字,找出后面的依赖。这显然是一种更牺牲性能的方法。虽然可以用var $ = require('jquery')这种“同步”的形式写代码,但终究不是一个最优的选择。

使用模块

在使用模块之前,我们可以通过require.config先配置每个js的路径,方便后续代码的书写。

1
2
3
4
5
6
7
8
9
// main.js的顶部,我定义了四个模块的path
require.config({
paths: {
simple: './simple',
jquery: '../jquery-3.3.1',
funcModule: './func-module',
depModule: './dep-module',
}
});

RequireJS调用模块的方式如下

1
2
// callback参数列表的顺序与deps中模块的顺序一致
require(deps, callback)
1
2
3
4
5
6
7
8
9
10
11
12
require(['simple', 'jquery', 'funcModule', 'depModule'], function(simple, $, funcModule, depModule) {
console.log(simple)
console.log($)
$('.word').css({
fontSize: '24px',
color: 'blue'
})
var result = funcModule.add(1,2)
console.log(result)

depModule.setColor('.word', 'yellow')
})

到这里我们已经掌握了RequireJS的最基本的用法了。

配置项

除了paths外,RequireJS还支持很多的配置项,便于我们快速开发。完整配置可以参考RequireJS 中文网

比较常用的有baseUrl,指定了js文件的查找基路径;还有shim,用来作为垫片支持那些不符合AMD规范的js。

baseUrl

经过本人测试,baseUrl的路径参考了引用require.js的入口html文件。我们看一下两种不同的文件路径配置就明白了。

首先看第一种
配置1

接着我们看一下第二种,我把requirejs.html移动到了一个html文件夹内。
配置2

这两种不同的文件路径下,baseUrl都必须参考requirejs.html的路径,否则就会发生引用404报错了。

shim

有些早期的js库并不支持AMD写法,所以需要在requirejs中配置shim才可以使用它们,shim写法如下:

1
2
3
4
5
6
7
8
9
10
require.config({
shim: {
"underscore" : {
exports : "_";
},
"jquery" : {
exports : "$";
}
}
})

扫一扫下方小程序码或搜索Tusi博客,即刻阅读最新文章!

Tusi博客

You forgot to set the qrcode for Alipay. Please set it in _config.yml.
You forgot to set the qrcode for Wechat. Please set it in _config.yml.
You forgot to set the business and currency_code for Paypal. Please set it in _config.yml.
You forgot to set the url Patreon. Please set it in _config.yml.
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×