前言:
为何咱们须要模块化开发,模块化开发的好处有哪些? 首先咱们先说一下非模块化的开发方式带来的弊端。 非模块化开发中会致使一些问题的出现,变量和函数命名可能相同,会形成变量污染和冲突,而且出错时候很难排查。耦合程度高,不符合软件开发中的高内聚和低耦合的原则,因此咱们就能够总结一下模块化开发的好处了:
① 解决项目中的变量污染问题。
② 开发效率高,有利于多人协同开发。
③ 职责单一,方便代码重用和维护 。
③ 解决文件依赖问题,无需关注引包顺序 。javascript
觉得做为服务器端的开发,不会通过网络传输,因此包的加载几乎都是瞬间完成的,只有加载完成了,才能执行操做,因此commonjs是同步的,nodejs就是实现了这种规范。html
有关规范的具体详情,找了两篇文章:
http://www.open-open.com/doc/view/f7df10bb81c347f79b436faa85dcfd81
http://blog.jobbole.com/49290/java
浏览器端的规范,由于全部的文件请求都要通过网络传输,不少文件的加载会有不肯定因素存在为了解决这个问题,浏览器端出来了这两个规范。node
异步模块定义规范(Asynchronous Module Definition)制定了定义模块的规则,这样模块和模块的依赖能够被异步加载。这和浏览器的异步加载模块的环境恰好适应(浏览器同步加载模块会致使性能、可用性、调试和跨域访问等问题)。具体规范连接在这里:中文版 英文版 ,requireJs就是AMD规范的实现。jquery
requirejs的基本使用:
① 引入requirejs包,而且设置入口文件git
<script data-main='js/main' src='http://apps.bdimg.com/libs/require.js/2.1.9/require.min.js'></script>
② 定义主模块 在main.js文件中github
define(['module1','module2',function(m1,m2) { // 说明:上面两个module是依赖模块,经过m1,m2的方式来使用 // 在这里咱们写本身的业务逻辑 todo // 若是咱们须要暴露出去,须要 return ,不是用exports或者module.exports // return {}; }]);
后续的使用,直接看文档吧,之后有机会再来补充。
requirejs官网
requirejs中文官网编程
通用模块定义 (Common Module Definition) 是 SeaJS 在推广过程当中对模块定义的规范化产出。相似的还有 CommonJS Modules/2.0 规范。
这些规范的目的都是为了 JavaScript 的模块化开发,特别是在浏览器端的。
目前这些规范的实现都能达成浏览器端模块化开发的目的。有两篇文档相关文档: 文档1 文档2 , 下面简要说一下seajs, 详细资料还得戳旁边的资料文档。json
seajs 的基本使用api
引入包文件
<script src='http://apps.bdimg.com/libs/seajs/2.3.0/sea.js'></script>
定义一个模块,好比在这个文件 student.js 中
define(function(require,exports,module){ function Student(){ this.name = '张三'; } // 对外暴露该模块的接口: module.exports = new Student(); })
使用模块:经过 seajs.use()
来实现,第一个参数是使用模块的路径,第二个回调函数中的参数是所要使用模块暴露出来的一个接口。
seajs.use('./student.js',function(stu){ console.log(stu.name); // 张三 });
seajs 暴露出接口的方式
module.exports
方式导出对象exports.属性或方法
方式导出seajs 内部的异步加载简单小demo — 写个小demo来阐述一下这个异步加载机制,在demo中,有如下几个文件 index.html ,loadJs.js ,module1.js:
index.html文件中的关键代码
<!--引入cdn上的seajs文件--> <script src='http://apps.bdimg.com/libs/seajs/2.3.0/sea.js'></script> <script src='loadJs.js'></script> <script> loadJs('module1.js',function(){ console.log('回调内的函数最后执行'); }); </script>
loadJs.js文件中的代码
function loadJs(path,callback) { var head = document.getElementsByTagName('head')[0]; var script = document.createElement('script'); script.setAttribute('src',path); head.appendChild(script); if(!/*@cc_on!*/false) { // 非IE浏览器 script.onload = function() { console.log('非IE浏览器'); callback(); } }else{ script.onreadystatechange = function(){ if(script.readyState === 'loaded' || script.readyState === 'complete') { console.log('IE'); callback(); } } } }
module1.js文件中的代码:
console.log('我是module1文件内的');
在Chrome下测试,最后控制台的输出结果:
我是module1文件内的 非IE浏览器 回调内的函数最后执行
总结:在模块加载的过程当中,先执行依赖模块内的逻辑,最后再去执行回调函数内的逻辑
seajs 异步加载 require 中的async方法:
require.async() 方法用来在模块内部异步加载模块,并在加载完成后执行指定回调。callback 参数可选。 require 是同步往下执行,require.async 则是异步回调执行。require.async 通常用来加载可延迟异步加载的模块。
seajs 的第三方依赖库的引入:好比 jQuery,咱们须要使用jquery,加入到咱们的项目中,首先咱们须要对jquery 进行改造,在高版本的jquery文件好比2.2中支持amd规范但不支持cmd规范,在文件中的最后找到以下代码:
if ( typeof define === "function" && define.amd ) { define( "jquery", [], function() { return jQuery; } ); }
咱们把它改造为:
if ( typeof define === "function" && (define.amd || define.cmd) ) { define( "jquery", [], function() { return jQuery; } ); }
而后咱们能够经过加载模块的方式,把jQuery加载进去了。
seajs的配置调试:
简单的写一写:
seajs.config({
// 别名配置 alias: { 'es5-safe': 'gallery/es5-safe/0.9.3/es5-safe', 'json': 'gallery/json/1.0.2/json', 'jquery': 'jquery/jquery/1.10.1/jquery' }, // 路径配置 paths: { 'gallery': 'https://a.alipayobjects.com/gallery' } })
经过对 sea.js 进行配置,让模块编写、开发调试更方便。
seajs 中的module
— 引自 玉伯
- 二者定位有差别。RequireJS 想成为浏览器端的模块加载器,同时也想成为 Rhino / Node 等环境的模块加载器。SeaJS 则专一于 Web 浏览器端,同时经过 Node 扩展的方式能够很方便跑在 Node 服务器端。
- 二者遵循的标准有差别。RequireJS 遵循的是 AMD(异步模块定义)规范,SeaJS 遵循的是 CMD (通用模块定义)规范。规范的不一样,致使了二者 API 的不一样。SeaJS 更简洁优雅,更贴近 CommonJS Modules/1.1 和 Node Modules 规范。
- 二者社区理念有差别。RequireJS 在尝试让第三方类库修改自身来支持 RequireJS,目前只有少数社区采纳。SeaJS 不强推,而采用自主封装的方式来“海纳百川”,目前已有较成熟的封装策略。
- 二者对调试等的支持有差别。SeaJS 经过插件,能够实现 Fiddler 中自动映射的功能,还能够实现自动 combo 等功能,很是方便便捷。RequireJS 无这方面的支持。
- 二者的插件机制有差别。RequireJS 采起的是在源码中预留接口的形式,源码中留有为插件而写的代码。SeaJS 采起的插件机制则与 Node 的方式一致:开放自身,让插件开发者可直接访问或修改,从而很是灵活,能够实现各类类型的插件。插件开发者可直接访问或修改,从而很是灵活,能够实现各类类型的插件。
- 对于依赖的模块,AMD 是提早执行,CMD 是延迟执行。不过 RequireJS 从 2.0 开始,也改为能够延迟执行(根据写法不一样,处理方式不一样)。CMD 推崇 as lazy as possible.
- CMD 推崇依赖就近,AMD 推崇依赖前置。