模块化:AMD规范

发布时间 2023-03-25 22:18:49作者: 斯斯20222

模块化:AMD规范

是席木木啊

已于 2022-10-02 22:11:59 修改

421
收藏
分类专栏: Vue 文章标签: AMD 模块化 javascript
版权

Vue
专栏收录该内容
41 篇文章2 订阅
订阅专栏
之前在《模块化:CommonJS规范》文中对CMD规范进行了介绍,并给出了服务端和浏览器端基于CommonJS模块化规范构建项目和模块化开发的示例demo。严格来讲,CommonJS这种模块化规范更加适用于服务器端编程,由于是同步的加载方式,并不十分适合浏览器端项目开发。

而此处介绍的AMD(Asynchronous Module Definition)-异步模块定义的规范——简称AMD规范,则采用异步方式加载模块,不会阻塞浏览器展示页面时,dom构建、css渲染等其它任务,模块内部的内容则采用同步加载方式,加载完成之后会立即执行主模块中定义的回调函数,真正启动web应用程序。

目录

AMD:基本语法

模块定义语法

模块引入语法

非AMD的传统模块化开发模式

早期模块化开发:IIFE模式+外部依赖引入

早期模块化开发:优缺点

AMD模块化开发模式

示例demo构建与测试

AMD模块化开发:AMD模块引入

AMD模块化开发:非AMD模块引入

AMD:基本语法
AMD作为一种模块化规范,有其对应的第三方库作为具体实现,最常用的就是RequireJS。也就是说,AMD规范的应用,需要借助RequireJS第三方库才能实现,点击此处,可访问其官网。

模块定义语法
AMD模块定义通过define语句实现,通常在开发过程中,基于define语法定义的模块可分为两类,

①没有依赖的模块,其语法如下,回调函数的内容即为自定义的模块的内容,

define(function(){
//todo:定义模块内容

//返回模块对象
return 模块;
})
②定义有依赖的模块,其语法为如下,

define(['module1',...,'modulen'],function(param) {
//todo:定义模块内容

//返回模块对象
return 模块;
});
其中:

[1] 参数1:数组形式的字符串,显示声明要注入的若干依赖模块;
[2] 参数2:param-回调函数,在模块加载之后会立即执行。

模块引入语法
通常是在主模块开头部分,会使用RequireJS库提供的requirejs.config()、requirejs()接口分别实现子模块的路径配置与非AMD模块到AMD模块的映射、子模块的加载和主模块内容的定义。

代码示例及其注释如下,

//配置子模块及其路径
requirejs.config({
baseUrl: 'js', //相对根目录的路劲
//默认相对于当前main.js主模块的相对路径
paths: {
dataService:'./modules/dataService',
alert:'./modules/alert',
jquery: './libs/jquery-3.6.1', //jquery默认支持amd规范
angular: './libs/angular', //angular.js-非amd规范的模块
},
shim:{
//配置非amd规范的js脚本库-将当前非amd文件规范化为AMD模块
angular: {
exports:'angular',
}
}
});


//引入子模块
requirejs(['alert','jquery','angular'],function (alert,$,angular){
alert.showMsg();
const domTitle = $('#title')[0].innerText;
console.log(domTitle);
console.log(angular)
});

非AMD的传统模块化开发模式
在出现RequireJS等AMD规范具体实现的第三方库之前,也已经诞生了不少模块化开发的方法,较为经典的就是“基于立即执行函数实现的模块模式开发”,也即:IIFE匿名闭包升级版本。在正式介绍AMD规范之前,有必要介绍一下早期的“模块模式”实现的模块化开发,及其缺点所在。

早期模块化开发:IIFE模式+外部依赖引入
①创建一个项目,其基本结构如下,其中:app.js为主模块、alert.js和dataService.js为子模块,index.html为将要引入主模块app.js的主页面。

 

②编写主模块和子模块的内容,

 

③在index.html主文件中引入app.js主模块,

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
</body>
<!--引入依赖模块-->
<script src="js/dataService.js"></script>
<script src="js/alert.js"></script>
<!--引入主模块-->
<script src="app.js"></script>
</html>
最终显示的内容如下,

 

早期模块化开发:优缺点
这种早期的借助立即执行函数实现的IIFE+外部依赖的模块化开发方式,其实就是现代模块化开发规范,包括ES6模块化规范的基石。其最大的优点就是:纯原生框架,无需借助任何第三方框架即可实现项目的模块化构建;其缺点是:需要在index.html主文件中引入主模块,以及主模块所依赖的所有的子模块,那么,在初始化index.html页面时,就需要发送若干次js文件的请求;并且还要保证子模块的引入顺序,否则就会出错。 对于大型项目来说,后期整体会变得越来越臃肿,甚至难以维护,因为模块之间的关系可能复杂到无法理解。

AMD模块化开发模式


前面已经提到,AMD只是一种开发规范,而RequireJS第三方JavaScript脚本库对其进行了实现。因此,Require.js作为一个异步的JavaScript模块加载器,下面的示例程序,必须要引入这个js脚本,可到官网进行下载:RequireJS。

示例demo构建与测试
①搭建如下的项目框架,基本结构如下图。

其中:js/libs-用来存放所依赖的第三方js脚本库;js/modules-用来存放自定义的AMD子模块;main.js-是Web应用程序的子模块;index.html-是Web应用程序的主页面。

 

②定义主模块和子模块,如下图所示,

 

其中,主模块main.js的内容如下,

//主模块
(function (){
//配置子模块及其路径
requirejs.config({
baseUrl: 'js', //相对根目录的路劲
//默认相对于当前main.js主模块的相对路径
paths: {
//引入自定义模块
dataService:'./modules/dataService',
alert:'./modules/alert',
//引入主模块
jquery: './libs/jquery-3.6.1'
}
});


//引入子模块
requirejs(['alert','jquery'],function (alert,$){
alert.showMsg();
const domTitle = $('#title')[0].innerText;
console.log(domTitle);
});
})();

③下载并在index.html文件中引入Require.js依赖库、主模块main.js,

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>AMD规范</title>
<!-- 引入子模块-->
<script data-main="js/main.js" src="js/libs/require.js"></script>
</head>
<body>
<div id="title">AMD规范实现</div>
</body>
</html>
④最终的实现效果如下,

 

AMD模块化开发:AMD模块引入
AMD模块化开发方式遇到的首要问题就是,如何引入自定义的、或者是第三方AMD子模块?

一般都是通过require.config()接口来实现的,示例代码如下,

//主模块
(function (){
//配置子模块及其路径
requirejs.config({
baseUrl: 'js', //相对根目录的路劲
//默认相对于当前main.js主模块的相对路径
paths: {
dataService:'./modules/dataService',
alert:'./modules/alert',
jquery: './libs/jquery-3.6.1', //jquery默认支持amd规范
},
});


//引入子模块
requirejs(['alert','jquery'],function (alert,$){
alert.showMsg();
const domTitle = $('#title')[0].innerText;
console.log(domTitle);
});
})();

上面的代码部分,baseUrl定义了子模块所在的根路径,这个路径是相对于项目的根路径来讲的;而paths参数部分,则对应子模块的配置信息。主要是子模块的模块id名称、与相对于baseUrl基路径的相对路径配置。

配置完毕之后,就可以在requirejs()接口中的第1个参数未知,加载需要的子模块,并将其作为回调函数的参数,就可以使用了。

AMD模块化开发:非AMD模块引入
在实际的开发中,我们遇到的有些第三方模块可能不是遵循AMD规范的,这时候就可以通过require.config()接口的shim参数将其映射为AMD模块。示例代码如下,将angular.js-非AMD第三方模块映射为AMD模块,并进行使用.

//主模块
(function (){
//配置子模块及其路径
requirejs.config({
baseUrl: 'js', //相对根目录的路劲
//默认相对于当前main.js主模块的相对路径
paths: {
dataService:'./modules/dataService',
alert:'./modules/alert',
jquery: './libs/jquery-3.6.1', //jquery默认支持amd规范
angular: './libs/angular', //angular.js-非amd规范的模块
},
shim:{
//配置非amd规范的js脚本库-将当前非amd文件规范化为AMD模块
angular: {
exports:'angular',
}
}
});


//引入子模块
requirejs(['alert','jquery','angular'],function (alert,$,angular){
alert.showMsg();
const domTitle = $('#title')[0].innerText;
console.log(domTitle);
console.log(angular)
});

————————————————
版权声明:本文为CSDN博主「是席木木啊」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_43524214/article/details/127146150