• 主页
  • 归档
  • 分类
  • 照片墙
所有文章 友情链接 关于我

  • 主页
  • 归档
  • 分类
  • 照片墙
  1. 1. CommonJS
  2. 2. AMD
  3. 3. require.js
    1. 3.1. data-main入口点
    2. 3.2. 子模块的编写方式
    3. 3.3. 主模块的编写方式
    4. 3.4. 加载非规范的模块
      1. 3.4.1. 模块依赖性声明

模块化编程(2)

2018-05-06 20:19:42
总字数 1.4k
预计阅读时间 5 分钟

模块存在的价值是为了能够更方便地复用代码 , 更加有利于功能的封装
但是如果要实现的话 , 就必须要求每个人都按照同样的方式去编写模块
目前通行的JavaScript模块规范有两种 , 分别是CommonJS和AMD

CommonJS

从node.js出现之后 , 将JavaScript用于服务器编程
同时也标志着JS的模块化编程正式诞生
在网页环境下 , 没有模块也不是特别大的问题 , 因为网页程序的复杂性和规模都相对有限 , 但是在服务器端就必须要有模块 , 否则服务器端程序就会难以扩展和维护

nodejs的模块系统 , 就是按照CommonJS规范实现的
这个规范当中 , 有一个全局方法 require , 用于加载模块

1
2
var mod1 = require("module1");
mod1.biz();

AMD

有了在服务端可用的模块化编程方式 , 大家很自然就想要在客户端也能实现的方式 , 并且最好能够兼容
这样同样的一个模块的代码 , 不用修改任何内容就可以同时应用于服务端和客户端

但是如果直接套用在nodejs当中的实现方式 , 就会存在线程阻塞的问题
也就是必须要等require方法执行完毕 , 加载运行这个模块的代码之后 , 后面的代码才会被执行
对于服务端来说 , 这并不是什么问题 , 因为代码都在本地 , 不可能出现长期阻塞的问题
但是对于客户端来说 , js文件需要发送http请求去获取 , 所以同步加载的方式就十分影响性能了

AMD ( Asynchronous Module Definition 异步模块定义 ) , 这种规范的要求是采用异步方式加载模块
形式如下 :

1
2
3
require(["module1"], function(mod) {
mod.biz();
});

规范只是约定一种形式 , 具体要应用的话需要有对应的库来实现
这里通过require.js来介绍

require.js

require.js官网

require.js主要解决两个问题

  1. 实现js文件的异步加载 , 避免网页失去响应
  2. 管理模块之间的依赖性 , 便于代码的编写和维护

使用require.js需要指定一个主模块 , 以及在主模块中可以去引入若干个子模块 , 主模块相当于是程序执行的入口
( 如果没有子模块的话就不需要require.js了 )

目录结构
require demo

data-main入口点

1
<script src="js/require.js" data-main="js/main"></script>

js目录下的main.js就是作为主模块 , 后面的.js可以省略

子模块的编写方式

require.js加载的模块 , 采用AMD规范 , 也就是说模块必须按照AMD的规范来写
模块必须采用特定的define函数来定义

1
2
3
4
5
6
7
8
//module1.js
define(function(){
return {
biz : function(){
console.log("子模块的方法");
}
}
})

这个函数返回的对象就是这个模块需要暴露出的对象

如果该模块需要依赖其他模块

1
2
3
4
5
6
7
8
9
//module2.js
define(["module1"],function(mod1){
function biz2() {
return mod1.biz() + "ok";
}
return {
biz : biz2
}
});

主模块的编写方式

1
2
3
4
5
//main.js
require(["modules/module1","modules/module2"],
function(mod1,mod2){
//mod1和mod2分别是在子模块中暴露出的对象
});

require函数接受两个参数 , 第一个参数是子模块的相对路径和名称 ( 如果在同一个路径下可以不加路径 ) , 必须是一个数组
第二个参数是子模块加载完成之后执行的回调函数

更加灵活的自定义加载

模块的引入采用的是子模块的js文件与主模块文件的相对位置
如果要加在的子模块较多 , 这么相对路径就需要加在每个子模块的前面
为了更清晰一些 , 我们可以采用下面的方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
require.config({
//注意这里的baseUrl是相对于引入主模块的页面的路径
//页面是 /require_demo/test.html
//子模块位于 /require_demo/other/module3.js
baseUrl : "./other/",
paths : {
mod3 : "module3",
mod4 : "module4"
}
});
//上面的代码相当于对子模块的路径创建了映射
//下面才是真正引入模块
require(["mod3","mod4"], function(mod3, mod4){
mod3.biz3();
mod4.biz4();
});

上面的写法其实就等价于

1
2
3
4
5
require(["../other/module3","../other/module4"],
function(mod3, mod4){
mod3.biz3();
mod4.biz4();
});

paths里面也可以直接使用完整的网络URL地址

加载非规范的模块

采用上面的方式去加载的子模块 , 模块当中必须按照AMD的规范去写
如果子模块本身并不符合这个要求
在不方便修改子模块的情况下 , 我们可以采用如下的方式去加载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
require.config({
shim : {
underscore : {
exports : "_"
}
},
paths : { //这部分并没有什么差别
underscore : "./plugins/underscore"
}
});

require(["underscore"], function(_) {
//测试代码
_.each([1,10,20],console.log);
});

未按照AMD规范编写的模块 , 通常采用的是暴露出一个变量放入到window当中作为全局变量 , 比如underscore这个库 , 暴露出的就是_

模块依赖性声明
1
2
3
4
5
6
7

shim : {
"jquery.scroll" : {
deps : ["jquery"],
exports : "jQuery.fn.scroll"
}
}
  • JavaScript
  • 模块化
  • JavaScript

扫一扫,分享到微信

二进制有关问题两则
模块化编程(1) 
© 2024 夏夜梦星辰
鲁ICP备19028444号
Power By Hexo
  • 所有文章
  • 友情链接
  • 关于我
{{searchItem.query}}
标签: 分类:
  • maven
  • 持续集成
  • JMS
  • 线程
  • JavaScript
  • ECMAScript6
  • 单元测试
  • Promise
  • Web Worker
  • 函数
  • prototype
  • 模块化
  • 正则表达式
  • 数据库
  • MongoDB
  • 索引
  • 集群
  • 全文检索
  • flutter
  • dart
  • git
  • 版本控制
  • linux
  • shell
  • docker
  • nginx
  • jenkins
  • opencv
  • vim
  • react
  • react native
  • 前端
  • css
  • HTML5
  • Hexo
  • sass
  • Three.js
  • TypeScript
  • Vue
  • 组件化
  • base64
  • webpack
  • nodejs
  • gulp
  • TensorFlow
  • 机器学习
  • 算法
  • 动态规划
  • 数据结构
  • Java
  • JavaScript
  • MongoDB
  • flutter
  • Git
  • linux
  • react
  • 前端杂烩
  • 男生女生
  • 算法
  • 十年饮冰,难凉热血
  • †少女癌†
  • 猫与向日葵
  • coderfun
  • JENKINS
  • API管理后台
愿你最终能接纳每一面每一种的自己
独自活着便是团圆